<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>冒险村放置 - 放置挂机游戏</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Microsoft YaHei', sans-serif;
        }
        body {
            background: #1a252f;
            color: #ecf0f1;
            overflow: hidden;
            background-image: linear-gradient(to bottom, #1a252f, #2c3e50);
            /* 移动端优化 */
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            -webkit-tap-highlight-color: transparent;
        }
        #game-container {
            position: relative;
            width: 100vw;
            height: 100vh;
            display: flex;
            flex-direction: column;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
        }
        #header {
            background: linear-gradient(135deg, #2c3e50, #1a252f);
            padding: 15px 30px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 3px solid #f39c12;
            box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
            z-index: 10;
        }
        #game-title {
            font-size: 32px;
            font-weight: bold;
            color: #f39c12;
            text-shadow: 3px 3px 6px rgba(0, 0, 0, 0.7);
            display: flex;
            align-items: center;
            gap: 15px;
            letter-spacing: 1px;
        }
        #game-title i {
            font-size: 36px;
            animation: pulse 2s infinite;
        }
        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.1); }
            100% { transform: scale(1); }
        }
        #resources {
            display: flex;
            gap: 15px;
            background: rgba(30, 42, 54, 0.95);
            padding: 10px 20px;
            border-radius: 12px;
            border: 2px solid #f39c12;
            box-shadow: 0 0 15px rgba(243, 156, 18, 0.3);
        }
        .resource {
            display: flex;
            align-items: center;
            gap: 12px;
            background: rgba(40, 55, 71, 0.8);
            padding: 10px 20px;
            border-radius: 8px;
            border: 1px solid #3498db;
            transition: all 0.3s ease;
            min-width: 180px;
        }
        .resource:hover {
            background: rgba(52, 152, 219, 0.3);
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4);
        }
        .resource-icon {
            width: 45px;
            height: 45px;
            background: linear-gradient(135deg, #f39c12, #e67e22);
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: bold;
            box-shadow: 0 0 10px rgba(243, 156, 18, 0.7);
            border: 2px solid #ffffff;
            font-size: 20px;
        }
        .resource-info {
            display: flex;
            flex-direction: column;
        }
        .resource-label {
            font-size: 14px;
            color: #bdc3c7;
            margin-bottom: 3px;
        }
        .resource-value {
            font-weight: bold;
            font-size: 22px;
            color: #f39c12;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }
        #controls {
            display: flex;
            gap: 15px;
        }
        button {
            background: linear-gradient(135deg, #3498db, #2980b9);
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: bold;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
            border: 2px solid #ffffff;
            font-size: 14px;
            letter-spacing: 0.5px;
            /* 触摸友好性优化 */
            min-height: 44px;
            min-width: 44px;
            touch-action: manipulation;
        }
        button:hover {
            background: linear-gradient(135deg, #2980b9, #2573a7);
            transform: translateY(-3px);
            box-shadow: 0 8px 15px rgba(0, 0, 0, 0.4);
        }
        button:active {
            transform: translateY(0);
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }
        #speed-controls {
            display: flex;
            background: rgba(30, 42, 54, 0.9);
            border-radius: 8px;
            overflow: hidden;
            border: 2px solid #3498db;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
        }
        #speed-controls button {
            border-radius: 0;
            padding: 12px 18px;
            border: none;
            background: transparent;
            color: #bdc3c7;
            font-weight: bold;
            transition: all 0.3s ease;
        }
        #speed-controls button.active {
            background: linear-gradient(135deg, #f39c12, #e67e22);
            color: #2c3e50;
            box-shadow: 0 0 10px rgba(243, 156, 18, 0.5);
        }
        #speed-controls button:hover:not(.active) {
            background: rgba(52, 152, 219, 0.3);
            color: #ecf0f1;
        }
        #main-content {
            display: flex;
            flex: 1;
            overflow: hidden;
        }
        #sidebar {
            width: 340px;
            background: linear-gradient(90deg, rgba(40, 55, 71, 0.95), rgba(30, 42, 54, 0.95));
            border-right: 3px solid #f39c12;
            padding: 0;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            box-shadow: 6px 0 20px rgba(0, 0, 0, 0.4);
            /* 移动端优化 */
            -webkit-overflow-scrolling: touch;
        }
        
        /* 页签系统样式 */
        .tab-navigation {
            display: flex;
            background: rgba(30, 42, 54, 0.95);
            border-bottom: 3px solid #f39c12;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }
        
        .tab-btn {
            flex: 1;
            background: rgba(40, 55, 71, 0.7);
            border: none;
            padding: 15px 5px;
            color: #bdc3c7;
            cursor: pointer;
            transition: all 0.3s ease;
            border-right: 1px solid #4a6572;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
            font-size: 12px;
            font-weight: bold;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            /* 触摸友好性优化 */
            min-height: 44px;
            min-width: 44px;
            touch-action: manipulation;
        }
        
        .tab-btn:last-child {
            border-right: none;
        }
        
        .tab-btn.active {
            background: linear-gradient(135deg, #f39c12, #e67e22);
            color: #2c3e50;
            box-shadow: 0 0 15px rgba(243, 156, 18, 0.5);
            transform: translateY(-2px);
        }
        
        .tab-btn:hover:not(.active) {
            background: rgba(52, 152, 219, 0.5);
            color: #ecf0f1;
            transform: translateY(-1px);
        }
        
        .tab-btn i {
            font-size: 18px;
        }
        
        .tab-content {
            display: none;
            padding: 20px;
            flex: 1;
            overflow-y: auto;
        }
        
        .tab-content.active {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        /* 统计数据样式 */
        .stat-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
            gap: 12px;
            margin-bottom: 20px;
        }
        
        .stat-item {
            background: rgba(40, 55, 71, 0.8);
            padding: 15px;
            border-radius: 10px;
            border: 2px solid #3498db;
            display: flex;
            flex-direction: column;
            align-items: center;
            text-align: center;
            font-size: 14px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
            transition: all 0.3s ease;
        }
        
        .stat-item:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 15px rgba(52, 152, 219, 0.4);
            border-color: #f39c12;
        }
        
        .stat-value {
            font-weight: bold;
            color: #f39c12;
            font-size: 22px;
            margin-top: 5px;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }
        
        .info-text {
            background: rgba(52, 152, 219, 0.3);
            padding: 20px;
            border-radius: 12px;
            border: 2px solid #3498db;
            font-size: 14px;
            line-height: 1.6;
            color: #ecf0f1;
            font-style: normal;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            text-align: center;
        }
        #text-game-container {
            flex: 1;
            position: relative;
            overflow: hidden;
            background: #1a252f;
            display: flex;
            flex-direction: column;
            padding: 20px;
            gap: 15px;
        }
        
        #text-game-container > div {
            flex: none;
        }
        
        #game-log {
            flex: 4 !important;
        }
        
        #game-status {
            flex: 1 !important;
        }
        
        #game-stats {
            flex: 2 !important;
        }
        
        #game-actions {
            flex: 1 !important;
        }
        
        #game-log {
            flex: 4;
            background: rgba(30, 42, 54, 0.9);
            border-radius: 12px;
            padding: 15px;
            border: 2px solid #3498db;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
            overflow-y: auto;
        }
        
        #game-log h3 {
            color: #f39c12;
            margin-bottom: 12px;
            font-size: 18px;
            text-align: center;
            border-bottom: 2px solid #3498db;
            padding-bottom: 6px;
        }
        
        #log-content {
            height: calc(100% - 30px);
            overflow-y: auto;
        }
        
        #log-content p {
            margin: 6px 0;
            padding: 6px 8px;
            border-left: 3px solid #3498db;
            background: rgba(40, 55, 71, 0.6);
            font-size: 14px;
            line-height: 1.4;
            border-radius: 0 6px 6px 0;
            transition: all 0.2s ease;
        }
        
        #log-content p:hover {
            background: rgba(52, 152, 219, 0.3);
            transform: translateX(3px);
        }
        
        #game-status {
            flex: 1;
            background: rgba(30, 42, 54, 0.9);
            border-radius: 12px;
            padding: 15px;
            border: 2px solid #3498db;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
        }
        
        #game-status h3 {
            color: #f39c12;
            margin-bottom: 12px;
            font-size: 18px;
            text-align: center;
            border-bottom: 2px solid #3498db;
            padding-bottom: 6px;
        }
        
        #status-content p {
            margin: 8px 0;
            font-size: 14px;
            padding: 8px;
            background: rgba(40, 55, 71, 0.5);
            border-radius: 6px;
            border-left: 3px solid #f39c12;
        }
        
        #status-content span {
            font-weight: bold;
            color: #f39c12;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }
        
        #game-stats {
            flex: 1;
            background: rgba(30, 42, 54, 0.9);
            border-radius: 12px;
            padding: 15px;
            border: 2px solid #3498db;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
        }
        
        #game-stats h3 {
            color: #f39c12;
            margin-bottom: 12px;
            font-size: 18px;
            text-align: center;
            border-bottom: 2px solid #3498db;
            padding-bottom: 6px;
        }
        
        #stats-content {
            height: calc(100% - 30px);
            overflow-y: auto;
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 10px;
        }
        
        .stat-row {
            display: flex;
            justify-content: space-between;
            font-size: 14px;
            padding: 8px;
            background: rgba(40, 55, 71, 0.5);
            border-radius: 6px;
            transition: all 0.2s ease;
            border-left: 3px solid #3498db;
        }
        
        .stat-row:hover {
            background: rgba(52, 152, 219, 0.3);
            transform: translateX(3px);
        }
        
        .stat-label {
            color: #bdc3c7;
        }
        
        .stat-value {
            color: #f39c12;
            font-weight: bold;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }
        
        /* 响应式设计 - 移动端适配 */
        @media screen and (max-width: 768px) {
            /* 调整整体布局 */
            #game-container {
                height: auto;
                min-height: 100vh;
                overflow: auto;
            }
            
            /* 调整头部布局 */
            #header {
                flex-direction: column;
                gap: 10px;
                padding: 10px;
            }
            
            #game-title {
                font-size: 24px;
                gap: 10px;
            }
            
            #game-title i {
                font-size: 28px;
            }
            
            /* 调整资源显示 */
            #resources {
                width: 100%;
                flex-wrap: wrap;
                justify-content: center;
                gap: 8px;
                padding: 8px;
            }
            
            .resource {
                min-width: 140px;
                padding: 8px 15px;
                gap: 8px;
            }
            
            .resource-icon {
                width: 35px;
                height: 35px;
                font-size: 16px;
            }
            
            .resource-label {
                font-size: 12px;
            }
            
            .resource-value {
                font-size: 18px;
            }
            
            /* 调整控制按钮 */
            #controls {
                width: 100%;
                justify-content: center;
                flex-wrap: wrap;
                gap: 8px;
            }
            
            button {
                padding: 10px 15px;
                font-size: 12px;
            }
            
            #speed-controls button {
                padding: 10px 12px;
                font-size: 12px;
            }
            
            /* 调整主内容区域 */
            #main-content {
                flex-direction: column;
            }
            
            #sidebar {
                width: 100%;
                border-right: none;
                border-top: 3px solid #f39c12;
            }
            
            /* 调整页签按钮 */
            .tab-btn {
                padding: 12px 5px;
                font-size: 10px;
            }
            
            .tab-btn i {
                font-size: 16px;
            }
            
            /* 调整统计数据网格 */
            .stat-grid {
                grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
                gap: 8px;
            }
            
            .stat-item {
                padding: 12px 10px;
                font-size: 12px;
            }
            
            .stat-value {
                font-size: 18px;
            }
            
            /* 调整信息文本 */
            .info-text {
                padding: 15px;
                font-size: 12px;
            }
            
            /* 调整游戏日志 */
            #text-game-container {
                padding: 10px;
                gap: 10px;
            }
            
            #game-log h3, #game-status h3, #game-stats h3 {
                font-size: 16px;
                padding-bottom: 4px;
            }
            
            #log-content p {
                font-size: 12px;
                padding: 4px 6px;
                margin: 4px 0;
            }
            
            #status-content p {
                font-size: 12px;
                padding: 6px;
                margin: 6px 0;
            }
            
            .stat-row {
                font-size: 12px;
                padding: 6px;
            }
        }
        
        /* 小屏幕设备优化 */
        @media screen and (max-width: 480px) {
            #header {
                padding: 8px 5px;
            }
            
            #game-title {
                font-size: 20px;
                gap: 8px;
            }
            
            #game-title i {
                font-size: 24px;
            }
            
            .resource {
                min-width: 120px;
                padding: 6px 12px;
                gap: 6px;
            }
            
            .resource-icon {
                width: 30px;
                height: 30px;
                font-size: 14px;
            }
            
            .resource-label {
                font-size: 11px;
            }
            
            .resource-value {
                font-size: 16px;
            }
            
            button {
                padding: 8px 12px;
                font-size: 11px;
            }
            
            #speed-controls button {
                padding: 8px 10px;
                font-size: 11px;
            }
            
            .tab-btn {
                padding: 10px 3px;
                font-size: 9px;
            }
            
            .stat-grid {
                grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
                gap: 6px;
            }
            
            .stat-item {
                padding: 10px 8px;
                font-size: 11px;
            }
            
            .stat-value {
                font-size: 16px;
            }
            
            .info-text {
                padding: 12px;
                font-size: 11px;
            }
        }
        
        #game-actions {
            flex: 1;
            background: rgba(30, 42, 54, 0.9);
            border-radius: 12px;
            padding: 20px;
            border: 2px solid #3498db;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.3);
        }
        
        #game-actions h3 {
            color: #f39c12;
            margin-bottom: 15px;
            font-size: 20px;
            text-align: center;
            border-bottom: 2px solid #3498db;
            padding-bottom: 8px;
        }
        
        #actions-content {
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
            justify-content: center;
        }
        
        #actions-content button {
            flex: 1;
            min-width: 130px;
            background: linear-gradient(135deg, #3498db, #2980b9);
            color: white;
            border: none;
            padding: 12px 15px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: bold;
            font-size: 14px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
            border: 2px solid #ffffff;
        }
        
        #actions-content button:hover {
            background: linear-gradient(135deg, #2980b9, #2573a7);
            transform: translateY(-3px);
            box-shadow: 0 8px 15px rgba(0, 0, 0, 0.4);
        }
        
        #actions-content button:active {
            transform: translateY(0);
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }
        
        .section {
            background: rgba(30, 42, 54, 0.8);
            border-radius: 8px;
            padding: 15px;
            border: 1px solid #3d566e;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        .section-title {
            font-size: 20px;
            margin-bottom: 15px;
            color: #f39c12;
            border-bottom: 2px solid #f39c12;
            padding-bottom: 8px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .building-list {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 15px;
            margin: 20px 0;
        }
        .building-item {
            background: rgba(40, 55, 71, 0.8);
            padding: 20px 15px;
            border-radius: 12px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            border: 2px solid #3498db;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 10px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
            /* 触摸友好性优化 */
            min-height: 44px;
            min-width: 44px;
            touch-action: manipulation;
        }
        .building-item.affordable {
            border-color: #2ecc71;
            box-shadow: 0 0 15px rgba(46, 204, 113, 0.5);
            transform: translateY(-3px);
        }
        
        @keyframes pulse {
            0% {
                box-shadow: 0 0 15px rgba(46, 204, 113, 0.5);
            }
            50% {
                box-shadow: 0 0 25px rgba(46, 204, 113, 0.8);
            }
            100% {
                box-shadow: 0 0 15px rgba(46, 204, 113, 0.5);
            }
        }
        
        @keyframes bounce {
            0%, 20%, 50%, 80%, 100% {
                transform: translateY(0);
            }
            40% {
                transform: translateY(-10px);
            }
            60% {
                transform: translateY(-5px);
            }
        }
        
        .building-item.affordable:hover {
            background: rgba(46, 204, 113, 0.2);
            transform: translateY(-5px);
            box-shadow: 0 8px 15px rgba(46, 204, 113, 0.7);
            animation: pulse 1.5s infinite;
        }
        
        .building-item.interacted {
            animation: bounce 0.5s ease;
        }
        
        .building-item.unaffordable {
            border-color: #e74c3c;
            opacity: 0.7;
            cursor: not-allowed;
        }
        
        .building-item.unaffordable:hover {
            background: rgba(40, 55, 71, 0.8);
            transform: none;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        
        .building-icon {
            width: 50px;
            height: 50px;
            background: linear-gradient(135deg, #f39c12, #e67e22);
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 24px;
            color: #2c3e50;
            border: 2px solid #ffffff;
            box-shadow: 0 0 10px rgba(243, 156, 18, 0.7);
        }
        
        .building-cost {
            font-size: 13px;
            color: #f39c12;
            margin-top: 8px;
            background: rgba(243, 156, 18, 0.2);
            padding: 5px 10px;
            border-radius: 15px;
            font-weight: bold;
        }
        
        .building-cost.insufficient {
            color: #e74c3c;
            background: rgba(231, 76, 60, 0.2);
            font-weight: bold;
        }
        .adventurer-list {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        .adventurer-item {
            background: #34495e;
            padding: 15px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s;
            border: 1px solid #4a6572;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .adventurer-item:hover {
            background: #3d566e;
            transform: translateX(3px);
        }
        .adventurer-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .adventurer-name {
            font-weight: bold;
            color: #f39c12;
            font-size: 18px;
        }
        .adventurer-class {
            background: #3498db;
            padding: 4px 10px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: bold;
        }
        .adventurer-details {
            display: flex;
            justify-content: space-between;
            font-size: 14px;
        }
        .stats-bar {
            height: 12px;
            background: #2c3e50;
            border-radius: 6px;
            overflow: hidden;
        }
        .stats-fill {
            height: 100%;
            border-radius: 6px;
        }
        .hp-fill {
            background: linear-gradient(to right, #e74c3c, #f39c12);
        }
        .mp-fill {
            background: linear-gradient(to right, #3498db, #2ecc71);
        }
        .hunger-fill {
            background: linear-gradient(to right, #8e44ad, #3498db);
        }
        #modal {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(40, 55, 71, 0.98);
            border: 2px solid #f39c12;
            border-radius: 12px;
            padding: 25px;
            z-index: 100;
            width: 600px;
            max-width: 90%;
            display: none;
            box-shadow: 0 0 30px rgba(0, 0, 0, 0.7);
            /* 移动端优化 */
            -webkit-overflow-scrolling: touch;
        }
        #modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #f39c12;
        }
        #modal-title {
            color: #f39c12;
            font-size: 24px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        #close-modal {
            background: #e74c3c;
            padding: 8px 15px;
            border-radius: 6px;
        }
        #modal-content {
            max-height: 70vh;
            overflow-y: auto;
            padding-right: 10px;
            /* 移动端优化 */
            -webkit-overflow-scrolling: touch;
        }
        .modal-section {
            margin-bottom: 20px;
            padding: 15px;
            background: rgba(30, 42, 54, 0.8);
            border-radius: 8px;
            border: 1px solid #3d566e;
        }
        .modal-section-title {
            font-size: 18px;
            color: #f39c12;
            margin-bottom: 15px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 15px;
        }
        .stat-item {
            display: flex;
            justify-content: space-between;
            padding: 8px 0;
            border-bottom: 1px solid #3d566e;
        }
        .equipment-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 12px;
        }
        .equipment-slot {
            background: #34495e;
            padding: 15px 10px;
            border-radius: 8px;
            text-align: center;
            border: 1px solid #4a6572;
            min-height: 80px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            gap: 5px;
            cursor: pointer;
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
        }
        .equipment-slot:hover {
            background: #3d566e;
            transform: scale(1.05);
            box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
        }
        .equipment-name {
            font-size: 14px;
            color: #f39c12;
            font-weight: bold;
            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
        }
        .equipment-stats {
            font-size: 12px;
        }
        .equipment-icon {
            font-size: 20px;
            margin-bottom: 5px;
        }
        .equipment-set-indicator {
            position: absolute;
            top: 5px;
            right: 5px;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: #e74c3c;
            border: 1px solid white;
        }
        .equipment-durability-bar {
            width: 90%;
            height: 4px;
            background: #2c3e50;
            border-radius: 2px;
            margin-top: 3px;
            overflow: hidden;
        }
        .equipment-durability-fill {
            height: 100%;
            background: #27ae60;
            border-radius: 2px;
            transition: width 0.3s;
        }
        .equipment-durability-low {
            background: #e74c3c;
        }
        .equipment-durability-medium {
            background: #f39c12;
        }
        .set-bonus-container {
            margin-top: 20px;
            padding: 15px;
            background: rgba(40, 55, 71, 0.7);
            border-radius: 8px;
            border: 1px solid #3498db;
        }
        .set-name {
            font-weight: bold;
            color: #f39c12;
            margin-bottom: 8px;
            font-size: 16px;
        }
        .set-bonus-active {
            color: #27ae60;
            font-weight: bold;
            margin: 5px 0;
        }
        .set-bonus-inactive {
            color: #e74c3c;
            font-style: italic;
            margin: 5px 0;
        }
        .inventory-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px;
        }
        .inventory-item {
            background: #34495e;
            padding: 12px 8px;
            border-radius: 8px;
            text-align: center;
            border: 1px solid #4a6572;
            font-size: 13px;
            cursor: pointer;
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
        }
        .inventory-item:hover {
            background: #3d566e;
            transform: scale(1.05);
            box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
        }
        .inventory-item-icon {
            font-size: 18px;
            margin-bottom: 5px;
        }
        .inventory-item-name {
            font-weight: bold;
            margin-bottom: 3px;
        }
        .inventory-item-level {
            font-size: 12px;
        }
        .inventory-item-set {
            position: absolute;
            top: 5px;
            right: 5px;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: #e74c3c;
            border: 1px solid white;
        }
        .log-container {
            max-height: 200px;
            overflow-y: auto;
            background: #2c3e50;
            padding: 10px;
            border-radius: 6px;
            border: 1px solid #3d566e;
        }
        .log-entry {
            font-size: 14px;
            margin-bottom: 8px;
            padding: 8px;
            background: #34495e;
            border-radius: 6px;
            border-left: 3px solid #f39c12;
        }
        .rarity-white { color: #ffffff; }
        .rarity-白色 { color: #ffffff; }
        .rarity-green { color: #1eff00; }
        .rarity-绿色 { color: #1eff00; }
        .rarity-blue { color: #0070dd; }
        .rarity-蓝色 { color: #0070dd; }
        .rarity-purple { color: #a335ee; }
        .rarity-紫色 { color: #a335ee; }
        .rarity-orange { color: #ff8000; }
        .rarity-橙色 { color: #ff8000; }
        .rarity-red { color: #e60000; }
        .rarity-红色 { color: #e60000; }
        .rarity-pink { color: #ff69b4; }
        .rarity-粉色 { color: #ff69b4; }
        .rarity-gold { color: #ffd700; }
        .rarity-金色 { color: #ffd700; }
        .rarity-rainbow { 
            background: linear-gradient(45deg, #ff0000, #ff8000, #ffff00, #00ff00, #0000ff, #8b00ff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        .rarity-彩虹 { 
            background: linear-gradient(45deg, #ff0000, #ff8000, #ffff00, #00ff00, #0000ff, #8b00ff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        
        /* 怪物稀有度颜色 */
        .rarity-普通 { color: #cccccc; }
        .rarity-精英 { color: #1eff00; }
        .rarity-首领 { color: #0070dd; }
        .rarity-传说 { color: #a335ee; }
        .rarity-神话 { color: #ff8000; }
        
        /* 新增的UI样式 */
        .building-upgrade-btn {
            background: #27ae60;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            margin-top: 5px;
            transition: all 0.3s;
        }
        
        .building-upgrade-btn:hover {
            background: #2ecc71;
            transform: scale(1.05);
        }
        
        .building-info-panel {
            position: absolute;
            background: rgba(40, 55, 71, 0.95);
            border: 2px solid #f39c12;
            border-radius: 8px;
            padding: 15px;
            z-index: 1000;
            min-width: 250px;
            display: none;
        }
        
        .building-level {
            color: #f39c12;
            font-weight: bold;
        }
        
        .building-income {
            color: #2ecc71;
            font-size: 14px;
        }
        
        .building-effect {
            color: #9b59b6;
            font-size: 13px;
            font-style: italic;
        }
        
        .quest-panel {
            position: fixed;
            top: 120px;
            left: 20px;
            background: rgba(40, 55, 71, 0.9);
            border: 2px solid #e74c3c;
            border-radius: 8px;
            padding: 15px;
            z-index: 1000;
            max-width: 300px;
            display: none;
        }
        
        .quest-header {
            color: #e74c3c;
            font-size: 18px;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .quest-item {
            background: rgba(52, 73, 94, 0.8);
            padding: 10px;
            border-radius: 6px;
            margin-bottom: 8px;
            border-left: 3px solid #e74c3c;
        }
        
        .quest-progress {
            background: #34495e;
            height: 6px;
            border-radius: 3px;
            margin-top: 5px;
            overflow: hidden;
        }
        
        .quest-progress-fill {
            background: linear-gradient(to right, #e74c3c, #f39c12);
            height: 100%;
            transition: width 0.3s;
        }
        
        .research-panel {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: rgba(40, 55, 71, 0.9);
            border: 2px solid #9b59b6;
            border-radius: 8px;
            padding: 15px;
            z-index: 1000;
            max-width: 280px;
            display: block;
        }
        
        .research-header {
            color: #9b59b6;
            font-size: 16px;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .research-item {
            background: rgba(52, 73, 94, 0.8);
            padding: 8px;
            border-radius: 4px;
            margin-bottom: 6px;
            font-size: 13px;
        }
        
        .research-available {
            border-left: 3px solid #2ecc71;
        }
        
        .research-locked {
            border-left: 3px solid #95a5a6;
            opacity: 0.6;
        }
        
        .research-available {
            border-left: 3px solid #2ecc71;
            cursor: pointer;
        }
        
        .research-active {
            border-left: 3px solid #f39c12;
            background: rgba(243, 156, 18, 0.1);
        }
        
        .research-completed {
            border-left: 3px solid #3498db;
            background: rgba(52, 152, 219, 0.1);
        }
        
        .research-progress-bar {
            background: #34495e;
            height: 6px;
            border-radius: 3px;
            margin-top: 8px;
            overflow: hidden;
        }
        
        .research-progress-fill {
            background: linear-gradient(to right, #9b59b6, #3498db);
            height: 100%;
            transition: width 0.3s;
        }
        
        .quest-complete {
            background: rgba(46, 204, 113, 0.2);
            border-left: 3px solid #2ecc71;
        }
        
        .quest-name {
            font-weight: bold;
            margin-bottom: 5px;
        }
        
        .quest-desc {
            font-size: 12px;
            color: #bdc3c7;
            margin-bottom: 8px;
        }
        
        .quest-progress-text {
            font-size: 11px;
            text-align: right;
            margin-top: 5px;
        }
        
        .quest-complete-text {
            color: #2ecc71;
            font-weight: bold;
            font-size: 11px;
            text-align: center;
            margin-top: 5px;
        }
        
        .floating-damage {
            position: absolute;
            font-weight: bold;
            font-size: 14px;
            pointer-events: none;
            z-index: 1000;
            animation: floatUp 1s ease-out forwards;
        }
        
        @keyframes floatUp {
            0% {
                opacity: 1;
                transform: translateY(0);
            }
            100% {
                opacity: 0;
                transform: translateY(-30px);
            }
        }
        
#tooltip {
            position: absolute;
            background: rgba(40, 55, 71, 0.95);
            border: 2px solid #f39c12;
            border-radius: 8px;
            padding: 12px;
            z-index: 1000;
            display: none;
            min-width: 200px;
            max-width: 300px;
            box-shadow: 0 0 15px rgba(0, 0, 0, 0.6);
        }
        .tooltip-header {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 10px;
            padding-bottom: 8px;
            border-bottom: 1px solid #f39c12;
        }
        .tooltip-icon {
            font-size: 20px;
        }
        .tooltip-name {
            font-weight: bold;
            color: #f39c12;
            font-size: 16px;
            text-align: center;
            flex: 1;
        }
        .tooltip-stats {
            font-size: 14px;
            margin: 5px 0;
        }
        .tooltip-stats strong {
            color: #3498db;
        }
        .tooltip-special {
            color: #f39c12;
            font-weight: bold;
        }
        .tooltip-set {
            color: #e74c3c;
            font-weight: bold;
        }
        .tooltip-bonus {
            color: #9b59b6;
            font-weight: bold;
        }
        .tooltip-status {
            font-size: 14px;
            margin-top: 8px;
            padding-top: 8px;
            border-top: 1px solid #34495e;
        }
        .tooltip-status.normal {
            color: #2ecc71;
        }
        .tooltip-status.injured {
            color: #e74c3c;
        }
        .tooltip-status.hungry {
            color: #f39c12;
        }
        .tooltip-status.dead {
            color: #8e44ad;
        }
        #monster-modal {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(40, 55, 71, 0.98);
            border: 2px solid #e74c3c;
            border-radius: 12px;
            padding: 25px;
            z-index: 100;
            width: 500px;
            max-width: 90%;
            display: none;
            box-shadow: 0 0 30px rgba(0, 0, 0, 0.7);
        }
        #monster-modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #e74c3c;
        }
        #monster-modal-title {
            color: #e74c3c;
            font-size: 24px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        #close-monster-modal {
            background: transparent;
            border: none;
            color: #e74c3c;
            font-size: 24px;
            cursor: pointer;
            padding: 5px;
            border-radius: 4px;
            transition: all 0.3s;
        }
        #close-monster-modal:hover {
            background: rgba(231, 76, 60, 0.2);
            transform: scale(1.1);
        }
        #equipment-modal {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(40, 55, 71, 0.98);
            border: 2px solid #f39c12;
            border-radius: 12px;
            padding: 25px;
            z-index: 100;
            width: 500px;
            max-width: 90%;
            display: none;
            box-shadow: 0 0 30px rgba(0, 0, 0, 0.7);
        }
        #equipment-modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #f39c12;
        }
        #equipment-modal-title {
            color: #f39c12;
            font-size: 24px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        #close-equipment-modal {
            background: #e74c3c;
            padding: 8px 15px;
            border-radius: 6px;
        }
        .equipment-details {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        .equipment-detail-row {
            display: flex;
            justify-content: space-between;
            padding: 8px 0;
            border-bottom: 1px solid #3d566e;
        }
        .equipment-action-buttons {
            display: flex;
            gap: 10px;
            margin-top: 20px;
        }
        .equipment-action-buttons button {
            flex: 1;
        }

        /* 自定义滚动条 */
        ::-webkit-scrollbar {
            width: 10px;
        }
        ::-webkit-scrollbar-track {
            background: #2c3e50;
            border-radius: 5px;
        }
        ::-webkit-scrollbar-thumb {
            background: #f39c12;
            border-radius: 5px;
        }
        ::-webkit-scrollbar-thumb:hover {
            background: #e67e22;
        }

        /* 动画效果 */
        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }
        .pulse {
            animation: pulse 2s infinite;
        }
        #notification {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(46, 204, 113, 0.9);
            color: white;
            padding: 15px;
            border-radius: 8px;
            display: none;
            z-index: 1000;
            box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
        }
        #resource-notification {
            position: absolute;
            top: 70px;
            right: 20px;
            background: rgba(241, 196, 15, 0.9);
            color: white;
            padding: 10px 15px;
            border-radius: 6px;
            display: none;
            z-index: 1000;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
        }

        /* 新增UI样式 */
        .title-system {
            position: absolute;
            top: 120px;
            right: 20px;
            background: rgba(40, 55, 71, 0.9);
            border: 1px solid #f39c12;
            border-radius: 8px;
            padding: 15px;
            z-index: 1000;
            max-width: 300px;
        }
        .title-header {
            color: #f39c12;
            font-size: 16px;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .current-title {
            background: linear-gradient(45deg, #f39c12, #e67e22);
            color: white;
            padding: 8px 12px;
            border-radius: 6px;
            font-weight: bold;
            text-align: center;
            margin-bottom: 10px;
        }
        .title-effects {
            font-size: 12px;
            color: #bdc3c7;
        }
        .achievement-popup {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: linear-gradient(45deg, #f39c12, #e67e22);
            color: white;
            padding: 20px;
            border-radius: 12px;
            z-index: 2000;
            display: none;
            text-align: center;
            box-shadow: 0 0 30px rgba(243, 156, 18, 0.5);
        }
        .achievement-title {
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 10px;
        }
        .achievement-desc {
            font-size: 14px;
        }
        
        /* 列表相关样式 */
        .list-section {
            margin: 20px 0;
            border: 2px solid #3498db;
            border-radius: 12px;
            background: rgba(40, 55, 71, 0.6);
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        }
        
        .list-header {
            padding: 15px 20px;
            background: linear-gradient(135deg, #2c3e50, #34495e);
            cursor: pointer;
            display: flex;
            align-items: center;
            gap: 12px;
            font-weight: bold;
            font-size: 16px;
            border-radius: 10px 10px 0 0;
            transition: all 0.3s ease;
            color: #ecf0f1;
        }
        
        .list-header:hover {
            background: linear-gradient(135deg, #34495e, #3d566e);
            transform: translateY(-2px);
        }
        
        .list-header i {
            transition: transform 0.3s ease;
            color: #f39c12;
        }
        
        .list-header.expanded i {
            transform: rotate(180deg);
        }
        
        .list-count {
            margin-left: auto;
            font-size: 16px;
            color: #f39c12;
            background: rgba(243, 156, 18, 0.2);
            padding: 3px 10px;
            border-radius: 12px;
        }
        
        .list-content {
            max-height: 400px;
            overflow-y: auto;
            transition: max-height 0.4s ease;
            background: rgba(52, 73, 94, 0.4);
            border-radius: 0 0 10px 10px;
        }
        
        .list-content.collapsed {
            max-height: 0;
            overflow: hidden;
        }
        
        .list-empty {
            padding: 30px;
            text-align: center;
            color: #7f8c8d;
            font-style: italic;
            font-size: 16px;
        }
        
        .list-item {
            padding: 15px 20px;
            border-bottom: 1px solid #3d566e;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            justify-content: space-between;
            align-items: center;
            /* 触摸友好性优化 */
            min-height: 44px;
            min-width: 44px;
            touch-action: manipulation;
        }
        
        .list-item:hover {
            background: rgba(52, 152, 219, 0.3);
            transform: translateX(5px);
        }
        
        .list-item:last-child {
            border-bottom: none;
            border-radius: 0 0 10px 10px;
        }
        
        .list-item-main {
            display: flex;
            flex-direction: column;
            flex: 1;
        }
        
        .list-item-title {
            font-weight: bold;
            color: #f39c12;
            margin-bottom: 5px;
            font-size: 16px;
        }
        
        .list-item-info {
            font-size: 14px;
            color: #bdc3c7;
            display: flex;
            gap: 15px;
        }
        
        .list-item-status {
            font-size: 12px;
            padding: 2px 8px;
            border-radius: 12px;
            font-weight: bold;
        }
        
        .status-alive {
            background: #2ecc71;
            color: white;
        }
        
        .status-dead {
            background: #e74c3c;
            color: white;
        }
        
        .status-injured {
            background: #f39c12;
            color: white;
        }
        
        .status-hungry {
            background: #9b59b6;
            color: white;
        }
        
        /* 怪物稀有度样式 */
        .monster-rank {
            font-size: 12px;
            padding: 2px 8px;
            border-radius: 12px;
            font-weight: bold;
        }
        
        .rank-普通 {
            background: #95a5a6;
            color: white;
        }
        
        .rank-精英 {
            background: #2ecc71;
            color: white;
        }
        
        .rank-首领 {
            background: #3498db;
            color: white;
        }
        
        .rank-传说 {
            background: #9b59b6;
            color: white;
        }
        
        .rank-神话 {
            background: #e74c3c;
            color: white;
        }
        
        /* 副本系统样式 */
        .dungeon-section {
            background: rgba(40, 55, 71, 0.8);
            border-radius: 12px;
            padding: 20px;
            border: 2px solid #3498db;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
            margin-bottom: 20px;
        }
        
        .dungeon-section h3 {
            color: #f39c12;
            margin-bottom: 15px;
            font-size: 20px;
            text-align: center;
            border-bottom: 2px solid #3498db;
            padding-bottom: 8px;
        }
        
        .dungeon-team-container {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 15px;
            margin: 20px 0;
        }
        
        .dungeon-team-slot {
            background: rgba(30, 42, 54, 0.9);
            border: 2px dashed #3498db;
            border-radius: 10px;
            padding: 15px 10px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            min-height: 100px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 8px;
        }
        
        .dungeon-team-slot:hover {
            background: rgba(52, 152, 219, 0.3);
            border-style: solid;
            transform: translateY(-3px);
        }
        
        .dungeon-team-slot.assigned {
            border-style: solid;
            background: rgba(40, 55, 71, 0.9);
        }
        
        .team-slot-icon {
            font-size: 24px;
            color: #3498db;
        }
        
        .team-slot-label {
            font-size: 14px;
            color: #bdc3c7;
        }
        
        .team-slot-name {
            font-weight: bold;
            color: #f39c12;
            font-size: 14px;
            margin-top: 5px;
        }
        
        .team-slot-remove {
            position: absolute;
            top: 5px;
            right: 5px;
            background: #e74c3c;
            color: white;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 12px;
            opacity: 0;
            transition: opacity 0.3s ease;
        }
        
        .dungeon-team-slot.assigned:hover .team-slot-remove {
            opacity: 1;
        }
        
        .team-slot-remove:hover {
            background: #c0392b;
        }
        
        /* 职业颜色类 */
        .class-warrior {
            color: #e74c3c;
        }
        
        .class-mage {
            color: #3498db;
        }
        
        .class-ranger {
            color: #2ecc71;
        }
        
        .class-priest {
            color: #f1c40f;
        }
        
        .class-rogue {
            color: #9b59b6;
        }
        
        .class-knight {
            color: #34495e;
        }
        
        .class-warlock {
            color: #8e44ad;
        }
        
        .class-druid {
            color: #16a085;
        }
        
        .class-assassin {
            color: #d35400;
        }
        
        .class-paladin {
            color: #f39c12;
        }
        
        .class-default {
            color: #bdc3c7;
        }
        
        .dungeon-action-btn {
            background: linear-gradient(135deg, #3498db, #2980b9);
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: bold;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
            border: 2px solid #ffffff;
            font-size: 14px;
            margin: 10px 5px;
            min-width: 120px;
        }
        
        .dungeon-action-btn:hover {
            background: linear-gradient(135deg, #2980b9, #2573a7);
            transform: translateY(-3px);
            box-shadow: 0 8px 15px rgba(0, 0, 0, 0.4);
        }
        
        .dungeon-action-btn:active {
            transform: translateY(0);
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }
        
        .dungeon-action-btn:disabled {
            background: #7f8c8d;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }
        
        .dungeon-records {
            background: rgba(30, 42, 54, 0.9);
            border-radius: 8px;
            padding: 15px;
            border: 1px solid #3d566e;
            max-height: 200px;
            overflow-y: auto;
        }
        
        .record-entry {
            padding: 10px;
            border-bottom: 1px solid #3d566e;
            font-size: 14px;
        }
        
        .record-entry:last-child {
            border-bottom: none;
        }
        
        .record-date {
            color: #bdc3c7;
            font-size: 12px;
        }
        
        .record-details {
            color: #f39c12;
            font-weight: bold;
            margin-top: 5px;
        }
        
        /* 冒险者卡片样式 */
        .adventurer-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 15px;
            margin: 20px 0;
        }
        
        .adventurer-card {
            background: rgba(40, 55, 71, 0.8);
            border-radius: 12px;
            padding: 15px;
            border: 2px solid #3498db;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        
        .adventurer-card:hover {
            background: rgba(52, 152, 219, 0.3);
            transform: translateY(-3px);
            box-shadow: 0 8px 15px rgba(0, 0, 0, 0.3);
        }
        
        .adventurer-header {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 15px;
        }
        
        .adventurer-icon {
            font-size: 24px;
        }
        
        .adventurer-name {
            font-weight: bold;
            font-size: 16px;
            flex: 1;
        }
        
        .adventurer-level {
            background: #f39c12;
            color: #2c3e50;
            padding: 3px 8px;
            border-radius: 12px;
            font-weight: bold;
            font-size: 14px;
        }
        
        .adventurer-stats {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 8px;
        }
    </style>
</head>
<body>
    <div id="game-container">
        <div id="header">
            <div id="game-title">
                <i class="fas fa-dragon"></i>
                <span>冒险村物语</span>
            </div>
            <div id="resources">
                <div class="resource">
                    <div class="resource-icon"><i class="fas fa-coins"></i></div>
                    <span class="resource-value" id="gold-value">1000</span>
                </div>
                <div class="resource">
                    <div class="resource-icon"><i class="fas fa-star"></i></div>
                    <span class="resource-value" id="charm-value">50</span>
                </div>
            </div>
            <div id="controls">
                <div id="speed-controls">
                    <button id="speed-1" class="active">1x</button>
                    <button id="speed-2">2x</button>
                    <button id="speed-3">3x</button>
                </div>
                <button id="save-btn"><i class="fas fa-save"></i> 保存</button>
                <button id="load-btn"><i class="fas fa-download"></i> 加载</button>
                <button id="pause-btn"><i class="fas fa-pause"></i> 暂停</button>
            </div>
        </div>

        <div id="main-content">
            <div id="sidebar">
                <!-- 页签导航 -->
                <div class="tab-navigation">
                    <button class="tab-btn active" data-tab="overview">
                        <i class="fas fa-home"></i>
                        <span>概览</span>
                    </button>
                    <button class="tab-btn" data-tab="adventurers">
                        <i class="fas fa-users"></i>
                        <span>冒险者</span>
                    </button>
                    <button class="tab-btn" data-tab="monsters">
                        <i class="fas fa-dragon"></i>
                        <span>怪物</span>
                    </button>
                    <button class="tab-btn" data-tab="buildings">
                        <i class="fas fa-building"></i>
                        <span>建筑</span>
                    </button>
                    <button class="tab-btn" data-tab="dungeon">
                        <i class="fas fa-dungeon"></i>
                        <span>副本</span>
                    </button>
                    <button class="tab-btn" data-tab="economy">
                        <i class="fas fa-coins"></i>
                        <span>经济</span>
                    </button>
                </div>

                <!-- 概览页签内容 -->
                <div class="tab-content active" id="overview-tab">
                    <div class="stat-grid">
                        <div class="stat-item">
                            <span>冒险者数量</span>
                            <span class="stat-value" id="overview-adventurer-count">3/12</span>
                        </div>
                        <div class="stat-item">
                            <span>怪物数量</span>
                            <span class="stat-value" id="overview-monster-count">0/30</span>
                        </div>
                        <div class="stat-item">
                            <span>建筑数量</span>
                            <span class="stat-value" id="overview-building-count">0</span>
                        </div>
                        <div class="stat-item">
                            <span>游戏时间</span>
                            <span class="stat-value" id="overview-game-time">0秒</span>
                        </div>
                        <div class="stat-item">
                            <span>击败怪物</span>
                            <span class="stat-value" id="overview-monsters-defeated">0</span>
                        </div>
                        <div class="stat-item">
                            <span>获得装备</span>
                            <span class="stat-value" id="overview-equipment-found">0</span>
                        </div>
                    </div>
                    <div class="info-text">
                        欢迎来到冒险村！这里是一个神奇的地方，冒险者们会自动探索、战斗和成长。你需要建设各种建筑来为他们提供服务，同时获得金币和魅力值来扩展你的村庄。
                    </div>
                </div>

                <!-- 冒险者页签内容 -->
                <div class="tab-content" id="adventurers-tab">
                    <div class="stat-grid">
                        <div class="stat-item">
                            <span>活跃冒险者</span>
                            <span class="stat-value" id="adventurer-active-count">0</span>
                        </div>
                        <div class="stat-item">
                            <span>死亡冒险者</span>
                            <span class="stat-value" id="adventurer-dead-count">0</span>
                        </div>
                        <div class="stat-item">
                            <span>平均等级</span>
                            <span class="stat-value" id="adventurer-avg-level">1</span>
                        </div>
                        <div class="stat-item">
                            <span>总经验值</span>
                            <span class="stat-value" id="adventurer-total-exp">0</span>
                        </div>
                    </div>
                    
                    <!-- 冒险者列表区域 -->
                    <div class="list-section">
                        <div class="list-header" onclick="game.toggleAdventurerList()">
                            <i class="fas fa-chevron-down" id="adventurer-list-arrow"></i>
                            <span>冒险者详细列表</span>
                            <span class="list-count" id="adventurer-list-count">(0)</span>
                        </div>
                        <div class="list-content collapsed" id="adventurer-list-content">
                            <div class="list-empty" id="adventurer-list-empty">暂无冒险者</div>
                        </div>
                    </div>
                    
                    <div class="info-text">
                        冒险者是村庄的核心力量。他们会自动探索地图、与怪物战斗、收集装备。每个冒险者都有独特的职业和属性，通过战斗获得经验值升级。点击列表中的冒险者可以查看详细信息。
                    </div>
                </div>

                <!-- 怪物页签内容 -->
                <div class="tab-content" id="monsters-tab">
                    <div class="stat-grid">
                        <div class="stat-item">
                            <span>普通怪物</span>
                            <span class="stat-value" id="monster-normal-count">0</span>
                        </div>
                        <div class="stat-item">
                            <span>精英怪物</span>
                            <span class="stat-value" id="monster-elite-count">0</span>
                        </div>
                        <div class="stat-item">
                            <span>首领怪物</span>
                            <span class="stat-value" id="monster-boss-count">0</span>
                        </div>
                        <div class="stat-item">
                            <span>最近刷新</span>
                            <span class="stat-value" id="monster-last-spawn">无</span>
                        </div>
                    </div>
                    
                    <!-- 怪物列表区域 -->
                    <div class="list-section">
                        <div class="list-header" onclick="game.toggleMonsterList()">
                            <i class="fas fa-chevron-down" id="monster-list-arrow"></i>
                            <span>怪物详细列表</span>
                            <span class="list-count" id="monster-list-count">(0)</span>
                        </div>
                        <div class="list-content collapsed" id="monster-list-content">
                            <div class="list-empty" id="monster-list-empty">暂无怪物</div>
                        </div>
                    </div>
                    
                    <div class="info-text">
                        怪物会定期在地图上刷新，它们拥有不同的等级和稀有度。击败怪物可以获得金币、装备和经验值。点击列表中的怪物可以查看详细信息。
                    </div>
                </div>

                <!-- 建筑页签内容 -->
                <div class="tab-content" id="buildings-tab">
                    <!-- 建筑列表区域 -->
                    <div class="list-section">
                        <div class="list-header" onclick="game.toggleBuildingList()">
                            <i class="fas fa-chevron-down" id="building-list-arrow"></i>
                            <span>建筑详细列表</span>
                            <span class="list-count" id="building-list-count">(0)</span>
                        </div>
                        <div class="list-content collapsed" id="building-list-content">
                            <div class="list-empty" id="building-list-empty">暂无建筑</div>
                        </div>
                    </div>
                    
                    <div class="building-list">
                        <div class="building-item" data-building="旅馆">
                            <div class="building-icon"><i class="fas fa-bed"></i></div>
                            <div>旅馆</div>
                            <div class="building-cost">300金</div>
                        </div>
                        <div class="building-item" data-building="饭店">
                            <div class="building-icon"><i class="fas fa-utensils"></i></div>
                            <div>饭店</div>
                            <div class="building-cost">250金</div>
                        </div>
                        <div class="building-item" data-building="武器店">
                            <div class="building-icon"><i class="fas fa-sword"></i></div>
                            <div>武器店</div>
                            <div class="building-cost">400金</div>
                        </div>
                        <div class="building-item" data-building="防具店">
                            <div class="building-icon"><i class="fas fa-shield-alt"></i></div>
                            <div>防具店</div>
                            <div class="building-cost">400金</div>
                        </div>
                        <div class="building-item" data-building="冒险公会">
                            <div class="building-icon"><i class="fas fa-landmark"></i></div>
                            <div>冒险公会</div>
                            <div class="building-cost">500金 10魅力</div>
                        </div>
                        <div class="building-item" data-building="市集">
                            <div class="building-icon"><i class="fas fa-store"></i></div>
                            <div>市集</div>
                            <div class="building-cost">350金 5魅力</div>
                        </div>
                        <div class="building-item" data-building="魔法塔">
                            <div class="building-icon"><i class="fas fa-hat-wizard"></i></div>
                            <div>魔法塔</div>
                            <div class="building-cost">800金 15魅力</div>
                        </div>
                        <div class="building-item" data-building="铁匠铺">
                            <div class="building-icon"><i class="fas fa-hammer"></i></div>
                            <div>铁匠铺</div>
                            <div class="building-cost">600金 8魅力</div>
                        </div>
                        <div class="building-item" data-building="炼金术师">
                            <div class="building-icon"><i class="fas fa-flask"></i></div>
                            <div>炼金术师</div>
                            <div class="building-cost">700金 12魅力</div>
                        </div>
                        <div class="building-item" data-building="图书馆">
                            <div class="building-icon"><i class="fas fa-book"></i></div>
                            <div>图书馆</div>
                            <div class="building-cost">450金 20魅力</div>
                        </div>
                        <div class="building-item" data-building="精灵树">
                            <div class="building-icon"><i class="fas fa-tree"></i></div>
                            <div>精灵树</div>
                            <div class="building-cost">1000金 25魅力</div>
                        </div>
                        <div class="building-item" data-building="竞技场">
                            <div class="building-icon"><i class="fas fa-fist-raised"></i></div>
                            <div>竞技场</div>
                            <div class="building-cost">1200金 30魅力</div>
                        </div>
                    </div>
                    <div class="info-text">
                        建筑为冒险者提供各种服务。点击建筑图标可以在地图上建造。每个建筑都有特定功能和升级效果，建造需要消耗金币和魅力值。
                    </div>
                </div>

                <!-- 副本页签内容 -->
                <div class="tab-content" id="dungeon-tab">
                    <div class="stat-grid">
                        <div class="stat-item">
                            <span>当前层数</span>
                            <span class="stat-value" id="dungeon-current-floor">0</span>
                        </div>
                        <div class="stat-item">
                            <span>最高记录</span>
                            <span class="stat-value" id="dungeon-highest-floor">0</span>
                        </div>
                        <div class="stat-item">
                            <span>队伍实力</span>
                            <span class="stat-value" id="dungeon-team-power">0</span>
                        </div>
                    </div>
                    
                    <div class="dungeon-section">
                        <h3>副本队伍</h3>
                        <div class="dungeon-team-container" id="dungeon-team-container">
                            <div class="dungeon-team-slot" data-slot="0">
                                <div class="team-slot-icon">
                                    <i class="fas fa-user-plus"></i>
                                </div>
                                <div class="team-slot-label">队员 1</div>
                            </div>
                            <div class="dungeon-team-slot" data-slot="1">
                                <div class="team-slot-icon">
                                    <i class="fas fa-user-plus"></i>
                                </div>
                                <div class="team-slot-label">队员 2</div>
                            </div>
                            <div class="dungeon-team-slot" data-slot="2">
                                <div class="team-slot-icon">
                                    <i class="fas fa-user-plus"></i>
                                </div>
                                <div class="team-slot-label">队员 3</div>
                            </div>
                            <div class="dungeon-team-slot" data-slot="3">
                                <div class="team-slot-icon">
                                    <i class="fas fa-user-plus"></i>
                                </div>
                                <div class="team-slot-label">队员 4</div>
                            </div>
                        </div>
                        <button id="dungeon-enter-btn" class="dungeon-action-btn">
                            <i class="fas fa-dungeon"></i> 进入副本
                        </button>
                        <button id="dungeon-reset-btn" class="dungeon-action-btn">
                            <i class="fas fa-redo"></i> 重置队伍
                        </button>
                    </div>
                    
                    <div class="dungeon-section">
                        <h3>副本记录</h3>
                        <div class="dungeon-records" id="dungeon-records">
                            <p>暂无副本记录</p>
                        </div>
                    </div>
                </div>

                <!-- 经济页签内容 -->
                <div class="tab-content" id="economy-tab">
                    <div class="stat-grid">
                        <div class="stat-item">
                            <span>当前金币</span>
                            <span class="stat-value" id="economy-gold">1000</span>
                        </div>
                        <div class="stat-item">
                            <span>当前魅力</span>
                            <span class="stat-value" id="economy-charm">50</span>
                        </div>
                        <div class="stat-item">
                            <span>建筑收入</span>
                            <span class="stat-value" id="economy-building-income">0/分钟</span>
                        </div>
                        <div class="stat-item">
                            <span>税收收入</span>
                            <span class="stat-value" id="economy-tax-income">0</span>
                        </div>
                        <div class="stat-item">
                            <span>总收入</span>
                            <span class="stat-value" id="economy-total-income">0</span>
                        </div>
                        <div class="stat-item">
                            <span>总支出</span>
                            <span class="stat-value" id="economy-total-expense">0</span>
                        </div>
                    </div>
                    <div class="info-text">
                        经济系统是村庄发展的基础。金币用于建设建筑和购买物品，魅力值用于吸引更多冒险者和解锁高级建筑。建筑会定期产生收入。
                    </div>
                </div>
            </div>

            <!-- 文字游戏主内容区域 -->
            <div id="text-game-container">
                <div id="game-log">
                    <h3>游戏日志</h3>
                    <div id="log-content">
                        <p>欢迎来到冒险村文字版！</p>
                        <p>游戏正在初始化中...</p>
                    </div>
                </div>
                
                <div id="game-status">
                    <h3>当前状态</h3>
                    <div id="status-content">
                        <p>冒险者: <span id="status-adventurers">0</span> | 怪物: <span id="status-monsters">0</span> | 建筑: <span id="status-buildings">0</span></p>
                        <p>金币: <span id="status-gold">1000</span> | 魅力: <span id="status-charm">50</span></p>
                        <p>已击败怪物: <span id="status-defeated">0</span> | 发现装备: <span id="status-equipment">0</span></p>
                        <p>税收收入: <span id="status-tax">0</span> | 游戏时间: <span id="status-time">0</span>秒</p>
                    </div>
                </div>
                
                <div id="game-stats">
                    <h3>详细统计</h3>
                    <div id="stats-content">
                        <div class="stat-grid" id="detailed-stats">
                            <!-- 详细统计信息将在这里动态生成 -->
                        </div>
                    </div>
                </div>
                
                <!-- <div id="game-actions">
                    <h3>快速操作</h3>
                    <div id="actions-content">
                        <button id="action-recruit">招募冒险者</button>
                        <button id="action-spawn-monster">生成怪物</button>
                        <button id="action-build-random">随机建造</button>
                    </div>
                </div> -->
            </div>
        </div>

        <!-- 称号系统 -->
        <div class="title-system" id="title-system">
            <div class="title-header">
                <i class="fas fa-crown"></i>
                <span>称号系统</span>
            </div>
            <div class="current-title" id="current-title">新手村长</div>
            <div class="title-effects" id="title-effects">
                金币获取 +5%
                冒险者招募速度 +10%
            </div>
        </div>

        <!-- 成就弹窗 -->
        <div class="achievement-popup" id="achievement-popup">
            <div class="achievement-title" id="achievement-title">获得称号！</div>
            <div class="achievement-desc" id="achievement-desc">恭喜获得新称号！</div>
        </div>

        <!-- 任务面板 -->
        <div class="quest-panel" id="quest-panel">
            <div class="quest-header">
                <i class="fas fa-scroll"></i>
                <span>任务板</span>
            </div>
            <div id="quest-list">
                <!-- 任务列表将通过JS动态生成 -->
            </div>
        </div>

        <!-- 研究面板 -->
        <div class="research-panel" id="research-panel">
            <div class="research-header">
                <i class="fas fa-flask"></i>
                <span>研究进度</span>
            </div>
            <div id="research-list">
                <!-- 研究列表将通过JS动态生成 -->
            </div>
        </div>

        <!-- 建筑信息面板 -->
        <div class="building-info-panel" id="building-info-panel">
            <div style="position: absolute; top: 5px; right: 5px;">
                <button onclick="document.getElementById('building-info-panel').style.display='none'" 
                        style="background: none; border: none; color: #ecf0f1; cursor: pointer; font-size: 16px;">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            <div id="building-info-content" style="margin-top: 20px;">
                <!-- 建筑信息将通过JS动态生成 -->
            </div>
        </div>

<!-- 冒险者详情模态框 -->
        <div id="modal">
            <div id="modal-header">
                <div id="modal-title"><i class="fas fa-user"></i> 冒险者详情</div>
                <button id="close-modal"><i class="fas fa-times"></i></button>
            </div>
            <div id="modal-content">
                <!-- 内容将通过JS动态生成 -->
            </div>
        </div>

        <!-- 怪物详情模态框 -->
        <div id="monster-modal">
            <div id="monster-modal-header">
                <div id="monster-modal-title"><i class="fas fa-dragon"></i> 怪物详情</div>
                <button id="close-monster-modal"><i class="fas fa-times"></i></button>
            </div>
            <div id="monster-modal-content">
                <!-- 内容将通过JS动态生成 -->
            </div>
        </div>

        <!-- 装备详情模态框 -->
        <div id="equipment-modal">
            <div id="equipment-modal-header">
                <div id="equipment-modal-title"><i class="fas fa-tshirt"></i> 装备详情</div>
                <button id="close-equipment-modal"><i class="fas fa-times"></i></button>
            </div>
            <div id="equipment-modal-content">
                <!-- 内容将通过JS动态生成 -->
            </div>
        </div>

        <!-- 工具提示 -->
        <div id="tooltip"></div>

        <!-- 通知 -->
        <div id="notification"></div>
        <div id="resource-notification"></div>
    </div>

    <script>
        // 游戏配置 - 扩展版本
        /**
         * 《冒险村放置》游戏配置类
         * 
         * 这个配置对象包含了游戏的所有核心参数和平衡性数值
         * 
         * 主要配置项说明：
         * 1. 画布配置 - 游戏渲染区域的尺寸设置
         * 2. 资源配置 - 初始金币和魅力值设置
         * 3. 冒险者配置 - 冒险者生成、上限和行为参数
         * 4. 怪物配置 - 怪物生成率和上限设置
         * 5. 建筑配置 - 各类建筑的成本和功能定义
         * 6. 装备配置 - 装备稀有度、词缀和槽位定义
         * 7. 职业配置 - 不同职业的属性成长和技能设置
         * 8. 系统配置 - 饥饿、税收等游戏机制参数
         */
        const Config = {
            // 游戏区域尺寸
            GAME_AREA_WIDTH: 1800,
            GAME_AREA_HEIGHT: 1500,

            // 资源相关配置
            INITIAL_GOLD: 1000,
            INITIAL_CHARM: 50,

            // 冒险者相关配置
            INITIAL_ADVENTURERS: 3,
            MAX_ADVENTURERS: 12,
            ADVENTURER_SPAWN_RATE: 0.0005,

            // 怪物相关配置
            MONSTER_SPAWN_RATE: 0.03,
            MONSTER_MAX_COUNT: 35,

            // 建筑相关配置
            BUILDING_COSTS: {
                '旅馆': { gold: 300, charm: 0 },
                '饭店': { gold: 250, charm: 0 },
                '武器店': { gold: 400, charm: 0 },
                '防具店': { gold: 400, charm: 0 },
                '冒险公会': { gold: 500, charm: 10 },
                '市集': { gold: 350, charm: 5 },
                '魔法塔': { gold: 800, charm: 15 },
                '铁匠铺': { gold: 600, charm: 8 },
                '炼金术师': { gold: 700, charm: 12 },
                '图书馆': { gold: 450, charm: 20 },
                '精灵树': { gold: 1000, charm: 25 },
                '竞技场': { gold: 1200, charm: 30 },
                '寺庙': { gold: 900, charm: 40 },
                '守卫塔': { gold: 1500, charm: 5 },
                '仓库': { gold: 300, charm: 0 },
                '研究所': { gold: 1800, charm: 35 }
            },
            
            // 建筑功能配置
            BUILDING_FUNCTIONS: {
                '旅馆': { type: 'rest', effect: 'hp_recovery', value: 15, cost: 8 }, // 提高恢复量，降低费用
                '饭店': { type: 'food', effect: 'hunger_recovery', value: 60, cost: 4 }, // 提高恢复量，降低费用
                '武器店': { type: 'shop', effect: 'weapon_trade', value: 1, cost: 0 },
                '防具店': { type: 'shop', effect: 'armor_trade', value: 1, cost: 0 },
                '冒险公会': { type: 'guild', effect: 'quest_board', value: 1, cost: 0 },
                '市集': { type: 'market', effect: 'general_trade', value: 1, cost: 0 },
                '魔法塔': { type: 'magic', effect: 'enchant', value: 1, cost: 40 }, // 降低费用
                '铁匠铺': { type: 'craft', effect: 'upgrade', value: 1, cost: 25 }, // 降低费用
                '炼金术师': { type: 'alchemy', effect: 'potion', value: 1, cost: 20 }, // 降低费用
                '图书馆': { type: 'knowledge', effect: 'exp_bonus', value: 0.15, cost: 0 }, // 提高经验加成
                '精灵树': { type: 'nature', effect: 'all_stats', value: 0.05, cost: 0 },
                '竞技场': { type: 'combat', effect: 'combat_exp', value: 0.2, cost: 0 },
                '寺庙': { type: 'spiritual', effect: 'mana_recovery', value: 20, cost: 0 },
                '守卫塔': { type: 'defense', effect: 'village_protection', value: 1, cost: 0 },
                '仓库': { type: 'storage', effect: 'inventory_expansion', value: 50, cost: 0 },
                '研究所': { type: 'research', effect: 'research_speed', value: 0.2, cost: 0 }
            },

            // 建筑配置（图标和效果）
            BUILDINGS: {
                '旅馆': { 
                    icon: 'fas fa-bed',
                    cost: 300,
                    charmCost: 0,
                    income: 10,
                    effects: {
                        '生命恢复': '提供冒险者生命值恢复服务',
                        '住宿服务': '为冒险者提供休息场所'
                    }
                },
                '饭店': { 
                    icon: 'fas fa-utensils',
                    cost: 250,
                    charmCost: 0,
                    income: 8,
                    effects: {
                        '饥饿恢复': '提供冒险者饥饿值恢复服务',
                        '食物供应': '为冒险者提供食物补给'
                    }
                },
                '武器店': { 
                    icon: 'fas fa-sword',
                    cost: 400,
                    charmCost: 0,
                    income: 12,
                    effects: {
                        '武器交易': '提供武器购买和出售服务',
                        '装备升级': '可升级冒险者武器'
                    }
                },
                '防具店': { 
                    icon: 'fas fa-shield-alt',
                    cost: 400,
                    charmCost: 0,
                    income: 12,
                    effects: {
                        '防具交易': '提供防具购买和出售服务',
                        '装备升级': '可升级冒险者防具'
                    }
                },
                '冒险公会': { 
                    icon: 'fas fa-landmark',
                    cost: 500,
                    charmCost: 10,
                    income: 15,
                    effects: {
                        '任务发布': '提供各种任务供冒险者完成',
                        '冒险者招募': '可招募新的冒险者'
                    }
                },
                '市集': { 
                    icon: 'fas fa-store',
                    cost: 350,
                    charmCost: 5,
                    income: 20,
                    effects: {
                        '商品交易': '提供各种商品交易服务',
                        '资源交换': '可进行资源交换'
                    }
                },
                '魔法塔': { 
                    icon: 'fas fa-hat-wizard',
                    cost: 800,
                    charmCost: 15,
                    income: 25,
                    effects: {
                        '魔法附魔': '可为装备添加魔法附魔',
                        '法术学习': '冒险者可学习新法术'
                    }
                },
                '铁匠铺': { 
                    icon: 'fas fa-hammer',
                    cost: 600,
                    charmCost: 8,
                    income: 18,
                    effects: {
                        '装备锻造': '可锻造高品质装备',
                        '装备修理': '可修理损坏的装备'
                    }
                },
                '炼金术师': { 
                    icon: 'fas fa-flask',
                    cost: 700,
                    charmCost: 12,
                    income: 22,
                    effects: {
                        '药水制作': '可制作各种药水',
                        '材料转换': '可将材料转换为其他资源'
                    }
                },
                '图书馆': { 
                    icon: 'fas fa-book',
                    cost: 450,
                    charmCost: 20,
                    income: 16,
                    effects: {
                        '知识学习': '提升冒险者经验值获取',
                        '技能研究': '可研究新的技能'
                    }
                },
                '精灵树': { 
                    icon: 'fas fa-tree',
                    cost: 1000,
                    charmCost: 25,
                    income: 30,
                    effects: {
                        '属性加成': '为所有冒险者提供属性加成',
                        '自然祝福': '提升村庄整体魅力值'
                    }
                },
                '竞技场': { 
                    icon: 'fas fa-fist-raised',
                    cost: 1200,
                    charmCost: 30,
                    income: 35,
                    effects: {
                        '战斗训练': '提升冒险者战斗经验值',
                        '技能提升': '可提升冒险者战斗技能'
                    }
                },
                '寺庙': { 
                    icon: 'fas fa-place-of-worship',
                    cost: 900,
                    charmCost: 40,
                    income: 28,
                    effects: {
                        '法力恢复': '提供冒险者法力值恢复服务',
                        '神圣祝福': '提升冒险者各项属性'
                    }
                },
                '守卫塔': { 
                    icon: 'fas fa-tower-observation',
                    cost: 1500,
                    charmCost: 5,
                    income: 20,
                    effects: {
                        '村庄防护': '减少怪物对村庄的威胁',
                        '安全保护': '提升村庄整体安全性'
                    }
                },
                '仓库': { 
                    icon: 'fas fa-warehouse',
                    cost: 300,
                    charmCost: 0,
                    income: 5,
                    effects: {
                        '物品存储': '扩展村庄物品存储空间',
                        '资源管理': '优化资源存储和管理'
                    }
                },
                '研究所': { 
                    icon: 'fas fa-microscope',
                    cost: 1800,
                    charmCost: 35,
                    income: 40,
                    effects: {
                        '科技研究': '解锁新的科技和功能',
                        '创新发展': '推动村庄技术进步'
                    }
                }
            },

            // 装备相关配置
            EQUIPMENT_RARITIES: ['白色', '绿色', '蓝色', '紫色', '橙色', '红色', '粉色', '金色', '彩虹'],
            EQUIPMENT_RARITY_COLORS: {
                '白色': '#ffffff',
                '绿色': '#1eff00',
                '蓝色': '#0070dd',
                '紫色': '#a335ee',
                '橙色': '#ff8000',
                '红色': '#e60000',
                '粉色': '#ff69b4',
                '金色': '#ffd700',
                '彩虹': 'linear-gradient(45deg, #ff0000, #ff8000, #ffff00, #00ff00, #0000ff, #8b00ff)'
            },
            EQUIPMENT_SLOTS: ['武器', '头盔', '胸甲', '护手', '护腿', '靴子', '项链', '戒指', '腰带', '护符'],
            WEAPON_TYPES: ['剑', '刀', '斧', '弓', '法杖', '匕首', '锤', '长枪', '法珠', '盾牌', '省手', '魔導器'],
            
            // 装备词缀配置
            EQUIPMENT_AFFIXES: {
                '攻击': ['锋利的', '致命的', '狂暴的', '精准的', '毁灭的', '燃烧的', '雷霆的'],
                '防御': ['坚固的', '守护的', '钢铁的', '神圣的', '不灭的', '大地的', '屏障的'],
                '生命': ['活力的', '健康的', '永恒的', '重生的', '恢复的', '疗愈的', '强壮的'],
                '速度': ['迅捷的', '轻灵的', '风行的', '幻影的', '闪电的', '瞬移的', '敏捷的'],
                '暴击': ['暴击的', '必杀的', '死神的', '狩猎的', '致命的', '给命的'],
                '魔法': ['智慧的', '奥术的', '魔力的', '神秘的', '元素的', '禁咒的'],
                '特殊': ['吸血的', '反射的', '神圣的', '传说的', '神话的']
            },
            
            // 装备套装配置
            EQUIPMENT_SETS: {
                '勇士套装': {
                    pieces: 3,
                    bonus: { attack: 10, defense: 5 },
                    class: ['战士'] // 专属于战士职业
                },
                '法师套装': {
                    pieces: 3,
                    bonus: { mp: 30, attack: 5 },
                    class: ['法师'] // 专属于法师职业
                },
                '游侠套装': {
                    pieces: 3,
                    bonus: { speed: 3, critRate: 0.05 },
                    class: ['弓箭手'] // 专属于弓箭手职业
                },
                '刺客套装': {
                    pieces: 3,
                    bonus: { critRate: 0.1, critDamage: 0.3 },
                    class: ['盗贼'] // 专属于盗贼职业
                },
                '圣骑士套装': {
                    pieces: 3,
                    bonus: { hp: 50, defense: 10 },
                    class: ['牧师', '战士'] // 牧师和战士可用
                },
                '元素套装': {
                    pieces: 5,
                    bonus: { attack: 15, mp: 50, allStats: 0.1 },
                    class: ['法师'] // 专属于法师职业
                },
                '龙鳞套装': {
                    pieces: 4,
                    bonus: { hp: 30, defense: 15, attack: 8 },
                    class: ['战士', '圣骑士'] // 战士和圣骑士可用
                },
                '暗影套装': {
                    pieces: 4,
                    bonus: { speed: 5, critRate: 0.08, attack: 10 },
                    class: ['盗贼', '刺客'] // 盗贼和刺客可用
                },
                '自然套装': {
                    pieces: 4,
                    bonus: { hp: 25, mp: 40, attack: 6, defense: 6 },
                    class: ['牧师', '法师'] // 牧师和法师可用
                },
                '风暴套装': {
                    pieces: 4,
                    bonus: { speed: 7, attack: 12, critRate: 0.05 },
                    class: ['弓箭手', '游侠'] // 弓箭手和游侠可用
                }
            },

            // 怪物相关配置
            MONSTER_TYPES: ['哥布林', '兽人', '骷髅', '蜘蛛', '狼', '巨魔', '元素生物', '龙类', '史莱姆', '蝙蝠', '僵尸', '幽灵', '恶魔', '天使', '石像鬼', '狮鹫', '九头蛇', '凤凰', '德鲁伊', '独眼巨人', '牛头人', '熊人', '剑齿虎', '巨型章鱼', '海怪', '雪怪', '火元素', '水元素', '土元素', '风元素', '机械构造体', '虚空行者', '时间扭曲者', '混沌魔物', '梦境吞噬者', '星界生物', '暗影刺客', '熔岩巨人', '冰霜领主', '雷霆使者', '森林守护者', '沙漠之王', '深海巨兽', '天空霸主', '地下领主', '瘟疫传播者', '死亡骑士', '灵魂收割者', '秩序守护者'],
            MONSTER_RANKS: ['普通', '精英', '首领', '传说', '神话'],
            MONSTER_BEHAVIORS: ['游荡', '巡逻', '守护', '狂暴', '群体', '潜行', '飞行', '遁地', '召唤', '自爆', '分裂', '变形', '传送', '诅咒', '祝福'],
            MONSTER_ATTRIBUTES: {
                '火': { color: '#ff4500', bonus: { attack: 1.2 } },
                '水': { color: '#4169e1', bonus: { defense: 1.2 } },
                '土': { color: '#8b4513', bonus: { hp: 1.3 } },
                '风': { color: '#32cd32', bonus: { speed: 1.5 } },
                '光': { color: '#ffd700', bonus: { allStats: 1.1 } },
                '暗': { color: '#8b008b', bonus: { critRate: 0.1 } },
                '雷': { color: '#9370db', bonus: { speed: 1.3, critRate: 0.05 } },
                '冰': { color: '#87ceeb', bonus: { defense: 1.1, speed: 0.8 } },
                '毒': { color: '#9acd32', bonus: { attack: 1.1, hp: 1.1 } },
                '金属': { color: '#c0c0c0', bonus: { defense: 1.4, speed: 0.7 } },
                '虚空': { color: '#4b0082', bonus: { allStats: 1.2 } },
                '混沌': { color: '#ff69b4', bonus: { attack: 1.3, defense: 0.7 } }
            },

            // 职业相关配置
            CLASSES: {
                '战士': {
                    attack: 5, defense: 5, hp: 20, mp: 0, speed: 0,
                    description: '近战物理职业，高生命值和防御力',
                    skills: ['重击', '防御姿态', '战吼'],
                    growth: { hp: 12, attack: 3, defense: 2, speed: 0.5 }
                },
                '法师': {
                    attack: 8, defense: 1, hp: 0, mp: 30, speed: 0,
                    description: '远程魔法职业，高魔法攻击力',
                    skills: ['火球术', '冰霜新星', '魔法护盾'],
                    growth: { hp: 6, attack: 4, defense: 0.5, speed: 1 }
                },
                '弓箭手': {
                    attack: 4, defense: 2, hp: 5, mp: 0, speed: 3,
                    description: '远程物理职业，高速度和暴击率',
                    skills: ['精准射击', '多重箭', '闪避'],
                    growth: { hp: 8, attack: 2.5, defense: 1, speed: 2 }
                },
                '盗贼': {
                    attack: 3, defense: 1, hp: 5, mp: 0, speed: 5,
                    description: '近战敏捷职业，高速度和暴击伤害',
                    skills: ['背刺', '隐身', '毒刃'],
                    growth: { hp: 7, attack: 2, defense: 0.8, speed: 2.5 }
                },
                '牧师': {
                    attack: 2, defense: 3, hp: 10, mp: 20, speed: 0,
                    description: '辅助职业，可以治疗队友',
                    skills: ['治疗术', '神圣之光', '祝福'],
                    growth: { hp: 9, attack: 1.5, defense: 1.5, speed: 0.8 }
                }
            },
            
            // 高级职业配置
            ADVANCED_CLASSES: {
                '战士': ['狂战士', '圣骑士', '武器大师'],
                '法师': ['元素法师', '死灵法师', '奥术师'],
                '弓箭手': ['神射手', '游侠', '暗影猎手'],
                '盗贼': ['刺客', '影舞者', '毒师'],
                '牧师': ['神圣牧师', '暗影牧师', '自然德鲁伊']
            },

            // 称号系统配置
            TITLES: {
                '新手村长': { condition: () => true, effects: { goldBonus: 0.05, recruitSpeed: 0.1 } },
                '怪物猎人': { condition: (game) => game.monstersDefeated >= 100, effects: { attackBonus: 0.1, dropRate: 0.05 } },
                '装备收藏家': { condition: (game) => game.equipmentFound >= 50, effects: { equipmentQuality: 0.15, goldBonus: 0.1 } },
                '富甲一方': { condition: (game) => game.gold >= 10000, effects: { taxRate: 0.02, buildingIncome: 0.2 } },
                '冒险大师': { condition: (game) => game.adventurers.length >= 10, effects: { recruitSpeed: 0.2, maxAdventurers: 2 } },
                '传说村长': { condition: (game) => game.monstersDefeated >= 500 && game.gold >= 20000, effects: { allStats: 0.1, dropRate: 0.1 } }
            },

            // 饥饿系统配置
            HUNGER_DECREASE_RATE: 0.0005, // 降低饥饿值下降速度，给玩家更多时间
            HUNGER_CRITICAL: 30, // 提高饥饿临界值，让冒险者更早去吃饭
            HUNGER_STARVING: 10, // 降低饥饿至死值，使饥饿系统更宽容

            // 税收配置
            TAX_RATE: 0.003, // 降低税收比例，减轻玩家负担
            DEATH_PENALTY: 0.05, // 降低死亡损失到5%
            RESPAWN_TIME: 8000, // 缩短复活时间到8秒

            // 装备词缀配置
            EQUIPMENT_AFFIXES: {
                '攻击': ['锋利的', '致命的', '狂暴的', '精准的', '毁灭的', '燃烧的', '雷霆的'],
                '防御': ['坚固的', '守护的', '钢铁的', '神圣的', '不灭的', '大地的', '屏障的'],
                '生命': ['活力的', '健康的', '永恒的', '重生的', '恢复的', '疗愈的', '强壮的'],
                '速度': ['迅捷的', '轻灵的', '风行的', '幻影的', '闪电的', '瞬移的', '敏捷的'],
                '暴击': ['暴击的', '必杀的', '死神的', '狩猎的', '致命的', '给命的'],
                '魔法': ['智慧的', '奥术的', '魔力的', '神秘的', '元素的', '禁咒的'],
                '特殊': ['吸血的', '反射的', '神圣的', '传说的', '神话的']
            },
            
            // 任务系统配置
            QUESTS: {
                'first_blood': {
                    name: '初战告捷',
                    description: '击败第一只怪物',
                    type: 'count',
                    target: 'monsters_defeated',
                    required: 1,
                    reward: { gold: 100, charm: 2 },
                    unlockBuilding: '武器店'
                },
                'monster_hunter': {
                    name: '怪物猎人',
                    description: '击败10只怪物',
                    type: 'count',
                    target: 'monsters_defeated',
                    required: 10,
                    reward: { gold: 200, charm: 5 },
                    unlockBuilding: '铁匠铺'
                },
                'build_inn': {
                    name: '建造旅馆',
                    description: '建造一座旅馆',
                    type: 'build',
                    target: '旅馆',
                    required: 1,
                    reward: { gold: 150, charm: 3 },
                    unlockBuilding: null
                },
                'collect_equipment': {
                    name: '装备收集家',
                    description: '收集20件装备',
                    type: 'count',
                    target: 'equipment_found',
                    required: 20,
                    reward: { gold: 500, charm: 10 },
                    unlockBuilding: '魔法塔'
                },
                'rich_town': {
                    name: '富裕的城镇',
                    description: '积累5000金币',
                    type: 'count',
                    target: 'gold',
                    required: 5000,
                    reward: { charm: 20 },
                    unlockBuilding: '研究所'
                },
                'first_dungeon': {
                    name: '初次探险',
                    description: '完成第一次副本探险',
                    type: 'count',
                    target: 'dungeon_completed',
                    required: 1,
                    reward: { gold: 300, charm: 5, equipment: '世界装' },
                    unlockBuilding: null
                }
            },
            
            // 副本系统配置
            DUNGEON_CONFIG: {
                MAX_TEAM_SIZE: 4, // 最大组队人数
                FLOOR_INCREMENT: 10, // 每10层属性增强
                STAT_INCREASE_PER_FLOOR: 0.01, // 每层属性增加1%
                EQUIPMENT_BOOST_PER_FLOOR: 0.01, // 每层装备属性增强1%
                BASE_MONSTER_LEVEL_DIFF: 0, // 基础怪物等级差
                MONSTER_STAT_MULTIPLIER: 1.0 // 副本怪物属性不降低
            },
            
            // 研究系统配置
            RESEARCH_TREE: {
                'basic_combat': {
                    name: '基础战斗',
                    description: '提升所有冒险者攻击力5%',
                    cost: { gold: 500, time: 60000 },
                    effects: { attackBonus: 0.05 },
                    prerequisites: [],
                    unlocked: false,
                    researched: false
                },
                'advanced_crafting': {
                    name: '高级制作',
                    description: '装备制作效率提升15%',
                    cost: { gold: 800, time: 120000 },
                    effects: { craftingBonus: 0.15 },
                    prerequisites: ['basic_combat'],
                    unlocked: false,
                    researched: false
                },
                'magic_enhancement': {
                    name: '魔法强化',
                    description: '魔法相关技能效果提升20%',
                    cost: { gold: 1200, time: 180000 },
                    effects: { magicBonus: 0.2 },
                    prerequisites: ['advanced_crafting'],
                    unlocked: false,
                    researched: false
                },
                'economic_growth': {
                    name: '经济增长',
                    description: '所有建筑收入提升10%',
                    cost: { gold: 1000, time: 150000 },
                    effects: { incomeBonus: 0.1 },
                    prerequisites: ['basic_combat'],
                    unlocked: false,
                    researched: false
                },
                'monster_knowledge': {
                    name: '怪物学',
                    description: '提升装备掉落率10%',
                    cost: { gold: 1500, time: 200000 },
                    effects: { dropRateBonus: 0.1 },
                    prerequisites: ['economic_growth'],
                    unlocked: false,
                    researched: false
                }
            },
        };

        /**
         * 《冒险村放置》游戏主类
         * 作者：AI助手
         * 描述：一个综合性的冒险村建设与管理游戏
         * 功能：冒险者管理、怪物战斗、装备系统、建筑系统、经济系统等
         * 
         * 主要特色：
         * - 自动化冒险者AI系统
         * - 丰富的建筑和装备系统
         * - 多样化的怪物和战斗机制
         * - 精美的界面和页签切换系统
         * - 完整的中文本地化支持
         * 
         * 系统架构说明：
         * 1. 游戏循环系统：基于requestAnimationFrame的高效游戏循环
         * 2. 资源管理系统：金币、魅力值等核心资源的生成和消耗
         * 3. 冒险者系统：AI控制的冒险者，包含状态机、行为决策和成长系统
         * 4. 怪物系统：自动生成的怪物，包含属性、行为和掉落机制
         * 5. 装备系统：丰富的装备类型、稀有度、词缀和套装效果
         * 6. 建筑系统：多种功能性建筑，提供不同服务和收入
         * 7. 经济系统：税收、建筑收入、研究投资等经济机制
         * 8. 称号系统：基于成就的称号解锁和属性加成
         * 9. 任务系统：引导玩家的游戏任务和目标
         * 10. 研究系统：科技树研究，提供长期增益效果
         */
        class Game {
            /**
             * 游戏构造函数
             * 初始化游戏的所有基本参数和系统组件
             * 这是整个游戏的核心类，负责管理游戏世界中的所有对象和系统
             */
            constructor() {
                // 游戏区域尺寸 - 定义游戏世界的大小
                this.gameAreaWidth = Config.GAME_AREA_WIDTH;   // 游戏区域宽度
                this.gameAreaHeight = Config.GAME_AREA_HEIGHT; // 游戏区域高度
                
                // 初始化游戏基本资源 - 玩家的核心资产
                this.gold = Config.INITIAL_GOLD;     // 金币 - 用于建造建筑、购买物品等
                this.charm = Config.INITIAL_CHARM;   // 魅力值 - 影响建筑效果和特殊能力

                // 初始化游戏对象数组 - 存储游戏世界中的各种实体
                this.buildings = [];     // 建筑列表 - 存储村庄中的所有建筑
                this.adventurers = [];   // 冒险者列表 - 存储村庄中的所有冒险者
                this.monsters = [];      // 怪物列表 - 存储世界中的所有怪物
                this.equipment = [];     // 装备列表 - 存储世界中的所有装备（暂时未使用）

                // 初始化游戏状态参数 - 控制游戏运行的核心状态
                this.gameTime = 0;                    // 游戏时间 - 以毫秒为单位的游戏运行时间
                this.gameSpeed = 1;                   // 游戏速度 - 控制游戏运行速度的倍数（1x, 2x, 3x）
                this.autoBattleEnabled = true;        // 自动战斗开关 - 控制冒险者是否自动寻找怪物战斗
                this.lastMonsterSpawn = '无';        // 最后一次怪物刷新 - 记录最近生成的怪物信息
                this.isPaused = false;                // 游戏是否暂停 - 控制游戏暂停/继续状态
                this.monsterCleanupTime = 300000;     // 怪物清理时间 - 5分钟（300秒）未被击败的怪物将被清理

                // 初始化游戏统计数据 - 记录玩家的游戏成就和进展
                this.monstersDefeated = 0;            // 击败怪物数量 - 统计玩家击败的怪物总数
                this.equipmentFound = 0;              // 获得装备数量 - 统计玩家获得的装备总数
                this.taxRevenue = 0;                  // 税收收入 - 当前周期内从冒险者收取的税收
                this.totalTaxCollected = 0;           // 总税收收入 - 游戏开始以来收取的税收总额

                // 初始化选中对象 - 用于UI交互时跟踪当前选中的对象
                this.selectedAdventurer = null;       // 当前选中的冒险者 - 用于显示详细信息
                this.selectedEquipment = null;        // 当前选中的装备 - 用于显示详细信息

                // 初始化称号系统 - 玩家的荣誉和特殊能力系统
                this.currentTitle = '新手村长';              // 当前称号 - 玩家当前拥有的称号
                this.unlockedTitles = ['新手村长'];        // 已解锁称号 - 玩家已获得的所有称号
                this.titleEffects = Config.TITLES['新手村长'].effects;  // 称号效果 - 当前称号提供的属性加成

                // 初始化成就系统 - 玩家的游戏成就展示系统
                this.achievementQueue = [];           // 成就队列 - 等待显示的成就列表
                this.isShowingAchievement = false;    // 是否正在显示成就 - 防止成就显示冲突

                // 初始化日志系统 - 控制是否输出调试日志
                this.enableConsoleLog = false;       // 控制台日志开关 - 控制是否输出console.log信息

                // 初始化副本系统
                this.dungeonTeamMembers = [];        // 副本队伍成员列表（用于队伍选择）
                this.dungeonTeams = [];              // 副本队伍列表（用于副本战斗）
                this.dungeonRecords = {};            // 副本记录（按冒险者ID）
                this.activeDungeon = null;           // 当前激活的副本
                this.dungeonsCompleted = 0;          // 完成的副本数量

                // 主循环与分批更新控制 - 防止单帧处理过多实体导致主线程阻塞
                this.mainLoopRunning = false;        // 标记主循环是否已启动，防止重复启动
                this.backgroundUpdateActive = false; // 后台更新激活标志（已有代码用到，但在构造器确保存在）
                this.monsterUpdateIndex = 0;         // 怪物分批更新游标
                this.adventurerUpdateIndex = 0;     // 冒险者分批更新游标
                this.updateBatchSize = 10;          // 每帧最多处理的实体数量（可根据需要调整）

                // 初始化税收系统 - 村庄经济的重要组成部分
                this.lastTaxTime = 0;                 // 上次税收时间 - 记录最近一次收税的时间点
                this.dailyTaxInterval = 60000;        // 税收间隔（1分钟为一天） - 收税的时间周期

                // 初始化任务系统 - 引导玩家游戏进程的系统
                this.activeQuests = [];               // 当前活跃任务 - 玩家正在进行的任务列表
                this.completedQuests = [];            // 已完成任务 - 玩家已完成的任务列表
                this.questProgress = {};              // 任务进度 - 各个任务的完成进度记录

                // 初始化研究系统 - 提供长期增益效果的科技树系统
                this.researchProgress = {};           // 研究进度 - 各个研究项目的完成状态
                this.activeResearch = null;           // 当前研究项目 - 正在进行的研究
                this.researchEffects = {};            // 研究效果 - 已完成研究提供的属性加成

                // 启动游戏 - 调用初始化方法开始游戏
                this.init();
            }

            /**
             * 游戏初始化方法
             * 设置事件监听器、初始化各系统、创建初始冒险者、启动游戏循环
             * 这是游戏启动时调用的核心方法，负责设置游戏的初始状态
             */
            init() {
                // 设置用户交互事件监听器
                this.setupEventListeners();
                
                // 初始化任务系统
                this.initializeQuests();
                
                // 初始化研究系统
                this.initializeResearch();

                // 创建初始冒险者 - 根据配置创建指定数量的初始冒险者
                for (let i = 0; i < Config.INITIAL_ADVENTURERS; i++) {
                    this.createAdventurer();
                }

                // 初始化游戏循环时间戳
                this.lastTime = 0;
                
                // 启动游戏主循环 - 使用requestAnimationFrame实现高效的渲染循环
                // 始终启动主循环，确保从后台回到前台时能正确运行
                this.mainLoopRunning = true;
                requestAnimationFrame(this.gameLoop.bind(this));

                // 更新称号显示界面
                this.updateTitleDisplay();
                
                // 更新任务显示界面
                this.updateQuestDisplay();
                
                // 更新研究显示界面
                this.updateResearchDisplay();
                
                // 初始化页签系统，默认显示概览页签
                this.switchTab('overview');
                
                // 初始化建筑按钮状态 - 延迟执行以确保DOM元素已加载
                setTimeout(() => {
                    this.updateBuildingButtonStates();
                }, 100);
            }

            setupEventListeners() {
                document.getElementById('speed-1').addEventListener('click', () => this.setGameSpeed(1));
                document.getElementById('speed-2').addEventListener('click', () => this.setGameSpeed(2));
                document.getElementById('speed-3').addEventListener('click', () => this.setGameSpeed(3));

                document.getElementById('save-btn').addEventListener('click', () => this.saveGame());
                document.getElementById('load-btn').addEventListener('click', () => this.loadGame());
                document.getElementById('pause-btn').addEventListener('click', () => this.togglePause());

                document.getElementById('close-modal').addEventListener('click', () => this.hideAdventurerModal());
                document.getElementById('close-equipment-modal').addEventListener('click', () => this.hideEquipmentModal());
                document.getElementById('close-monster-modal').addEventListener('click', () => this.hideMonsterModal());

                // 页签切换事件监听器
                document.querySelectorAll('.tab-btn').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        const tabName = e.currentTarget.getAttribute('data-tab');
                        this.switchTab(tabName);
                    });
                });

                // 为建筑按钮添加事件监听器
                setTimeout(() => {
                    document.querySelectorAll('.building-item').forEach(item => {
                        // 移除所有现有的事件监听器
                        const newBtn = item.cloneNode(true);
                        item.parentNode.replaceChild(newBtn, item);
                        
                        // 添加新的点击事件监听器
                        newBtn.addEventListener('click', (e) => {
                            e.preventDefault();
                            e.stopPropagation();
                            const type = newBtn.getAttribute('data-building');
                            this.debugLog('点击建筑按钮:', type);
                            if (type) {
                                // 在文字游戏中，点击建筑显示建筑信息面板
                                this.showBuildingTypeInfo(type);
                            } else {
                                this.debugLog('建筑类型未定义');
                            }
                        });
                    });
                }, 150);

                // 页面可见性变化事件监听器 - 确保后台运行
                document.addEventListener('visibilitychange', () => {
                    this.debugLog('Visibility change detected in setupEventListeners:', document.hidden ? 'hidden' : 'visible');
                    if (document.hidden) {
                        // 页面隐藏时启动后台更新机制
                        if (!this.isPaused) {
                            this.debugLog('Starting background update in setupEventListeners');
                            this.backgroundUpdateActive = true;
                            this.lastBackgroundUpdate = Date.now();
                            setTimeout(() => {
                                if (this.backgroundUpdateActive) {
                                    this.backgroundUpdate();
                                }
                            }, 100);
                        }
                    } else {
                        // 页面显示时停止后台更新，切换回正常循环
                        this.debugLog('Stopping background update in setupEventListeners');
                        this.backgroundUpdateActive = false;
                        if (this.pageHiddenTime) {
                            const hiddenDuration = Date.now() - this.pageHiddenTime;
                            this.gameTime += hiddenDuration;
                            this.pageHiddenTime = null;
                        }
                        // 确保主循环继续运行
                        if (this.mainLoopRunning) {
                            requestAnimationFrame(this.gameLoop.bind(this));
                        }
                    }
                });

                // 页面失去焦点和获得焦点事件监听器
                window.addEventListener('blur', () => {
                    this.debugLog('Window blur detected in setupEventListeners');
                    this.windowBlurred = true;
                    // 窗口失去焦点时启动后台更新
                    if (!this.isPaused) {
                        this.debugLog('Starting background update on blur in setupEventListeners');
                        this.backgroundUpdateActive = true;
                        this.lastBackgroundUpdate = Date.now();
                        // 立即启动后台更新
                        setTimeout(() => {
                            if (this.backgroundUpdateActive) {
                                this.backgroundUpdate();
                            }
                        }, 100);
                    }
                });

                window.addEventListener('focus', () => {
                    this.debugLog('Window focus detected in setupEventListeners');
                    this.windowBlurred = false;
                    // 窗口获得焦点时停止后台更新
                    this.backgroundUpdateActive = false;
                });

                // 点击建筑信息面板外部关闭面板
                document.addEventListener('click', (e) => {
                    const panel = document.getElementById('building-info-panel');
                    if (panel && panel.style.display === 'block') {
                        // 检查点击是否在面板内部
                        if (!panel.contains(e.target) && e.target.closest('.building-info-panel') !== panel) {
                            panel.style.display = 'none';
                        }
                    }
                });

                const tooltip = document.getElementById('tooltip');
                document.addEventListener('mousemove', (e) => {
                    tooltip.style.left = (e.pageX + 10) + 'px';
                    tooltip.style.top = (e.pageY + 10) + 'px';
                });
                
                // 添加快速操作按钮事件监听器（如果元素存在）
                const actionRecruit = document.getElementById('action-recruit');
                if (actionRecruit) {
                    actionRecruit.addEventListener('click', () => {
                        if (this.adventurers.length < Config.MAX_ADVENTURERS + (this.titleEffects.maxAdventurers || 0)) {
                            const adventurer = this.createAdventurer();
                            if (adventurer) {
                                this.showNotification(`成功招募冒险者: ${adventurer.name} (${adventurer.class})`);
                            }
                        } else {
                            this.showNotification('冒险者数量已达上限！', 'error');
                        }
                    });
                }
                
                // 添加副本队伍事件委托处理
                document.addEventListener('click', (e) => {
                    // 处理副本队伍槽位点击事件
                    const teamSlot = e.target.closest('.dungeon-team-slot');
                    if (teamSlot) {
                        const teamContainer = document.getElementById('dungeon-team-container');
                        if (teamContainer && teamContainer.contains(teamSlot)) {
                            const index = parseInt(teamSlot.dataset.index);
                            // 检查是否点击的是移除按钮
                            const removeBtn = e.target.closest('.team-slot-remove');
                            if (removeBtn) {
                                const removeIndex = parseInt(removeBtn.dataset.index);
                                this.removeAdventurerFromDungeonTeam(removeIndex);
                            } else {
                                this.selectDungeonTeamMember(index);
                            }
                        }
                    }
                });

                const actionSpawnMonster = document.getElementById('action-spawn-monster');
                if (actionSpawnMonster) {
                    actionSpawnMonster.addEventListener('click', () => {
                        if (this.monsters.length < Config.MONSTER_MAX_COUNT) {
                            const monster = this.createMonster();
                            if (monster) {
                                this.showNotification(`生成怪物: ${monster.rank}${monster.type} Lv.${monster.level}`);
                            }
                        } else {
                            this.showNotification('怪物数量已达上限！', 'error');
                        }
                    });
                }
                
                const actionBuildRandom = document.getElementById('action-build-random');
                if (actionBuildRandom) {
                    actionBuildRandom.addEventListener('click', () => {
                        // 在文字游戏中，随机显示一个建筑的信息
                        const buildingTypes = Object.keys(Config.BUILDING_COSTS);
                        const randomType = buildingTypes[Math.floor(Math.random() * buildingTypes.length)];
                        this.showBuildingTypeInfo(randomType);
                    });
                }
            }

            setGameSpeed(speed) {
                this.gameSpeed = speed;
                document.querySelectorAll('#speed-controls button').forEach((btn, i) => {
                    if (i + 1 === speed) {
                        btn.classList.add('active');
                    } else {
                        btn.classList.remove('active');
                    }
                });
            }

            /**
             * 页签切换功能
             * @param {string} tabName - 要切换到的页签名称
             */
            switchTab(tabName) {
                // 页签切换时可能触发的重绘和更新操作
                this.debugLog(`切换到页签: ${tabName}`);
                
                // 移除所有按钮的活跃状态
                document.querySelectorAll('.tab-btn').forEach(btn => {
                    btn.classList.remove('active');
                });
                
                // 隐藏所有页签内容
                document.querySelectorAll('.tab-content').forEach(content => {
                    content.classList.remove('active');
                });
                
                // 激活当前按钮和内容
                const activeBtn = document.querySelector(`[data-tab="${tabName}"]`);
                const activeContent = document.getElementById(`${tabName}-tab`);
                
                if (activeBtn) activeBtn.classList.add('active');
                if (activeContent) activeContent.classList.add('active');
                
                // 更新页签内容
                this.updateTabContent(tabName);
                
                // 注意：页签切换本身不会导致实体重新分散
                // 但是浏览器的focus/blur事件可能会影响游戏循环的deltaTime计算
                // 这可能会影响移动算法的表现，使聚集现象看起来被缓解
            }

            /**
             * 更新页签内容
             * @param {string} tabName - 页签名称
             */
            updateTabContent(tabName) {
                switch(tabName) {
                    case 'overview':
                        this.updateOverviewTab();
                        break;
                    case 'adventurers':
                        this.updateAdventurersTab();
                        break;
                    case 'monsters':
                        this.updateMonstersTab();
                        break;
                    case 'buildings':
                        this.updateBuildingsTab();
                        break;
                    case 'dungeon':
                        this.updateDungeonTab();
                        break;
                    case 'economy':
                        this.updateEconomyTab();
                        break;
                }
            }

            /**
             * 更新概览页签
             */
            /**
             * 更新概览页签 - UI显示系统
             * 实时更新游戏概览信息的显示状态
             * 包括冒险者、怪物、建筑等核心统计数据
             * 
             * 显示内容：
             * 1. 冒险者数量统计（当前/最大）
             * 2. 怪物数量统计（当前/最大）
             * 3. 建筑数量统计（当前总数）
             * 4. 游戏运行时间（秒）
             * 5. 击败怪物总数
             * 6. 发现装备总数
             * 
             * 数据计算：
             * - 冒险者最大数量 = 基础上限 + 称号加成
             * - 游戏时间以秒为单位显示
             * - 所有统计数据实时更新
             * 
             * DOM安全机制：
             * - 所有元素获取后检查存在性
             * - 避免对不存在元素的操作
             * - 稳定的文本内容更新
             */
            updateOverviewTab() {
                const adventurerCount = document.getElementById('overview-adventurer-count');
                if (adventurerCount) {
                    adventurerCount.textContent = `${this.adventurers.length}/${Config.MAX_ADVENTURERS + (this.titleEffects.maxAdventurers || 0)}`;
                }
                
                const monsterCount = document.getElementById('overview-monster-count');
                if (monsterCount) {
                    monsterCount.textContent = `${this.monsters.length}/${Config.MONSTER_MAX_COUNT}`;
                }
                
                const buildingCount = document.getElementById('overview-building-count');
                if (buildingCount) {
                    buildingCount.textContent = this.buildings.length;
                }
                
                const gameTime = document.getElementById('overview-game-time');
                if (gameTime) {
                    gameTime.textContent = `${Math.floor(this.gameTime / 1000)}秒`;
                }
                
                const monstersDefeated = document.getElementById('overview-monsters-defeated');
                if (monstersDefeated) {
                    monstersDefeated.textContent = this.monstersDefeated;
                }
                
                const equipmentFound = document.getElementById('overview-equipment-found');
                if (equipmentFound) {
                    equipmentFound.textContent = this.equipmentFound;
                }
            }

            /**
             * 更新冒险者页签 - UI显示系统
             * 实时更新冒险者页签中的统计数据和列表
             * 包括活跃/死亡冒险者数量、平均等级、总经验值等
             * 支持列表展开/收起状态的动态更新
             * 
             * 统计数据：
             * 1. 活跃冒险者数量（非死亡状态）
             * 2. 死亡冒险者数量
             * 3. 平均等级（所有冒险者）
             * 4. 总经验值（所有冒险者）
             * 5. 冒险者列表计数
             * 
             * 列表更新机制：
             * 1. 检查列表是否处于展开状态
             * 2. 只在展开时更新列表内容
             * 3. 收起时保留旧内容节省性能
             * 4. 计数显示实时更新
             * 
             * 数据计算：
             * - 活跃数量 = 非死亡状态冒险者
             * - 死亡数量 = 死亡状态冒险者
             * - 平均等级 = 总等级/冒险者数量
             * - 总经验 = 所有冒险者经验之和
             * 
             * DOM安全机制：
             * - 所有元素获取后检查存在性
             * - 避免对不存在元素的操作
             * - 稳定的文本内容更新
             * - 列表状态检查确保正确更新
             */
            updateAdventurersTab() {
                const activeCount = this.adventurers.filter(a => a.state !== 'dead').length;
                const deadCount = this.adventurers.filter(a => a.state === 'dead').length;
                const avgLevel = this.adventurers.length > 0 ? 
                    Math.floor(this.adventurers.reduce((sum, a) => sum + a.level, 0) / this.adventurers.length) : 1;
                const totalExp = this.adventurers.reduce((sum, a) => sum + a.exp, 0);

                const activeCountEl = document.getElementById('adventurer-active-count');
                if (activeCountEl) activeCountEl.textContent = activeCount;
                
                const deadCountEl = document.getElementById('adventurer-dead-count');
                if (deadCountEl) deadCountEl.textContent = deadCount;
                
                const avgLevelEl = document.getElementById('adventurer-avg-level');
                if (avgLevelEl) avgLevelEl.textContent = avgLevel;
                
                const totalExpEl = document.getElementById('adventurer-total-exp');
                if (totalExpEl) totalExpEl.textContent = totalExp;
                
                // 更新冒险者列表计数
                const listCountEl = document.getElementById('adventurer-list-count');
                if (listCountEl) listCountEl.textContent = `(${this.adventurers.length})`;
                
                // 如果列表展开了，更新列表内容
                const listContent = document.getElementById('adventurer-list-content');
                if (listContent && !listContent.classList.contains('collapsed')) {
                    // 只有当冒险者数量发生变化时才更新列表内容，避免频繁刷新
                    const currentCount = listContent.querySelectorAll('.list-item').length;
                    if (currentCount !== this.adventurers.length) {
                        this.updateAdventurerListContent();
                    }
                }
            }
            
            /**
             * 切换冒险者列表展开/收起状态 - UI交互系统
             * 控制冒险者列表的展开和收起动画效果
             * 同步更新相关的UI元素状态和样式
             * 在展开时自动更新列表内容
             * 
             * 交互机制：
             * 1. 点击列表标题区域触发展开/收起
             * 2. 通过CSS类控制展开/收起状态
             * 3. 同步更新箭头图标方向
             * 4. 展开时高亮标题区域
             * 
             * 状态管理：
             * - collapsed类：控制列表内容显示/隐藏
             * - expanded类：控制标题区域高亮状态
             * - 展开时自动更新列表内容
             * - 收起时保留内容节省性能
             * 
             * DOM元素控制：
             * 1. 箭头元素：旋转动画指示状态
             * 2. 内容区域：显示/隐藏控制
             * 3. 标题区域：高亮状态控制
             * 
             * 性能优化：
             * - 只在展开时更新列表内容
             * - 收起时保留DOM结构
             * - 避免不必要的重排重绘
             */
            toggleAdventurerList() {
                const arrow = document.getElementById('adventurer-list-arrow');
                const content = document.getElementById('adventurer-list-content');
                const header = document.querySelector('#adventurers-tab .list-header');
                
                if (content && arrow && header) {
                    if (content.classList.contains('collapsed')) {
                        // 展开列表
                        content.classList.remove('collapsed');
                        header.classList.add('expanded');
                        this.updateAdventurerListContent();
                    } else {
                        // 收起列表
                        content.classList.add('collapsed');
                        header.classList.remove('expanded');
                    }
                }
            }
            
            /**
             * 更新冒险者列表内容 - UI列表系统
             * 动态生成并更新冒险者列表的详细内容
             * 根据冒险者状态显示不同样式和信息
             * 支持空列表状态的特殊显示
             * 
             * 列表结构：
             * 1. 空列表状态：显示提示信息
             * 2. 非空列表：显示详细冒险者信息
             * 3. 每项包含：名称、等级、职业、HP、EXP
             * 4. 状态指示：正常/受伤/饥饿/死亡
             * 
             * 状态显示：
             * - 正常状态：绿色标识
             * - 受伤状态：HP低于30%时显示
             * - 饥饿状态：饥饿值低于30时显示
             * - 死亡状态：死亡状态时显示
             * 
             * 交互功能：
             * 1. 点击列表项打开详细信息模态框
             * 2. 实时状态颜色标识
             * 3. 数值信息精确显示
             * 
             * 性能优化：
             * 1. 列表更新前清空旧内容
             * 2. 空列表时显示特殊提示
             * 3. DOM操作最小化
             * 4. 元素复用减少创建开销
             * 
             * 数据展示：
             * - 冒险者名称：唯一标识
             * - 等级职业：Lv.等级 职业
             * - 生命值：当前/最大值
             * - 经验值：当前经验值
             */
            updateAdventurerListContent() {
                const listContent = document.getElementById('adventurer-list-content');
                const listEmpty = document.getElementById('adventurer-list-empty');
                
                if (!listContent) return;
                
                if (this.adventurers.length === 0) {
                    if (listEmpty) listEmpty.style.display = 'block';
                    // 清空列表项
                    const existingItems = listContent.querySelectorAll('.list-item');
                    existingItems.forEach(item => item.remove());
                } else {
                    if (listEmpty) listEmpty.style.display = 'none';
                    
                    // 定期更新冒险者列表项，确保信息是最新的
                    const existingItems = listContent.querySelectorAll('.list-item');
                    if (existingItems.length !== this.adventurers.length) {
                        // 清空旧的列表项
                        existingItems.forEach(item => item.remove());
                        
                        // 添加新的冒险者列表项
                        this.adventurers.forEach(adventurer => {
                            const listItem = document.createElement('div');
                            listItem.className = 'list-item';
                            listItem.onclick = () => this.showAdventurerModal(adventurer);
                            
                            // 确定冒险者状态
                            let statusClass = 'status-alive';
                            let statusText = '正常';
                            
                            if (adventurer.state === 'dead') {
                                statusClass = 'status-dead';
                                statusText = '死亡中';
                            } else if (adventurer.hp < adventurer.maxHp * 0.3) {
                                statusClass = 'status-injured';
                                statusText = '受伤';
                            } else if (adventurer.hunger < 30) {
                                statusClass = 'status-hungry';
                                statusText = '饥饿';
                            }
                            
                            listItem.innerHTML = `
                                <div class="list-item-main">
                                    <div class="list-item-title">${adventurer.name}</div>
                                    <div class="list-item-info">
                                        <span>Lv.${adventurer.level} ${adventurer.class}</span>
                                        <span>EXP: ${adventurer.exp}</span>
                                    </div>
                                </div>
                                <div class="list-item-status ${statusClass}">${statusText}</div>
                            `;
                            
                            // 鼠标悬停事件通过事件委托处理，避免内存泄漏
                            
                            listContent.appendChild(listItem);
                        });
                        
                        // 为列表容器添加事件委托处理鼠标悬停事件
                        listContent.onmouseover = (e) => {
                            const listItem = e.target.closest('.list-item');
                            if (listItem) {
                                const index = Array.from(listContent.children).indexOf(listItem);
                                if (index >= 0 && index < this.adventurers.length) {
                                    const adventurer = this.adventurers[index];
                                    let statusText = '正常';
                                    if (adventurer.state === 'dead') {
                                        statusText = '死亡中';
                                    } else if (adventurer.hp < adventurer.maxHp * 0.3) {
                                        statusText = '受伤';
                                    } else if (adventurer.hunger < 30) {
                                        statusText = '饥饿';
                                    }
                                    
                                    const tooltip = document.getElementById('tooltip');
                                    if (tooltip) {
                                        tooltip.innerHTML = `
                                            <div class="tooltip-name">${adventurer.name}</div>
                                            <div class="tooltip-stats">
                                                <div>职业: ${adventurer.class}</div>
                                                <div>等级: Lv.${adventurer.level}</div>
                                                <div>生命值: ${Math.floor(adventurer.hp)}/${adventurer.maxHp}</div>
                                                <div>魔法值: ${Math.floor(adventurer.mp)}/${adventurer.maxMp}</div>
                                                <div>饥饿值: ${Math.floor(adventurer.hunger)}/${adventurer.maxHunger}</div>
                                                <div>状态: ${statusText}</div>
                                                <div>位置: (${Math.floor(adventurer.x)}, ${Math.floor(adventurer.y)})</div>
                                            </div>
                                        `;
                                        tooltip.style.display = 'block';
                                    }
                                }
                            }
                        };
                        
                        listContent.onmouseout = () => {
                            const tooltip = document.getElementById('tooltip');
                            if (tooltip) {
                                tooltip.style.display = 'none';
                            }
                        };
                    } else {
                        // 如果数量相同，更新现有列表项的所有信息，确保数据是最新的
                        const items = listContent.querySelectorAll('.list-item');
                        items.forEach((item, index) => {
                            const adventurer = this.adventurers[index];
                            if (adventurer) {
                                // 更新标题和基本信息
                                const titleElement = item.querySelector('.list-item-title');
                                if (titleElement) {
                                    titleElement.textContent = adventurer.name;
                                }
                                
                                const infoElement = item.querySelector('.list-item-info');
                                if (infoElement) {
                                    infoElement.innerHTML = `
                                        <span>Lv.${adventurer.level} ${adventurer.class}</span>
                                        <span>EXP: ${adventurer.exp}</span>
                                    `;
                                }
                                
                                // 更新状态显示
                                let statusClass = 'status-alive';
                                let statusText = '正常';
                                
                                if (adventurer.state === 'dead') {
                                    statusClass = 'status-dead';
                                    statusText = '死亡中';
                                } else if (adventurer.hp < adventurer.maxHp * 0.3) {
                                    statusClass = 'status-injured';
                                    statusText = '受伤';
                                } else if (adventurer.hunger < 30) {
                                    statusClass = 'status-hungry';
                                    statusText = '饥饿';
                                }
                                
                                const statusElement = item.querySelector('.list-item-status');
                                if (statusElement) {
                                    statusElement.className = 'list-item-status ' + statusClass;
                                    statusElement.textContent = statusText;
                                }
                            }
                        });
                    }
                }
            }

            /**
             * 更新怪物页签
             */
            /**
             * 更新怪物页签 - UI显示系统
             * 实时更新怪物页签中的统计数据和列表
             * 包括不同稀有度怪物数量、最近刷新信息等
             * 支持列表展开/收起状态的动态更新
             * 
             * 统计数据：
             * 1. 普通怪物数量统计
             * 2. 精英怪物数量统计
             * 3. 首领怪物数量统计（包括传说、神话）
             * 4. 最近刷新怪物信息
             * 5. 怪物列表计数
             * 
             * 稀有度分类：
             * - 普通：基础怪物
             * - 精英：较强怪物
             * - 首领：强大怪物（首领/传说/神话）
             * 
             * 列表更新机制：
             * 1. 检查列表是否处于展开状态
             * 2. 只在展开时更新列表内容
             * 3. 收起时保留旧内容节省性能
             * 4. 计数显示实时更新
             * 
             * 数据展示：
             * - 按稀有度分类统计
             * - 最近刷新怪物显示
             * - 列表计数实时更新
             * 
             * DOM安全机制：
             * - 所有元素获取后检查存在性
             * - 避免对不存在元素的操作
             * - 稳定的文本内容更新
             * - 列表状态检查确保正确更新
             */
            updateMonstersTab() {
                const normalCount = this.monsters.filter(m => m.rank === '普通').length;
                const eliteCount = this.monsters.filter(m => m.rank === '精英').length;
                const bossCount = this.monsters.filter(m => m.rank === '首领' || m.rank === '传说' || m.rank === '神话').length;

                const normalCountEl = document.getElementById('monster-normal-count');
                if (normalCountEl) normalCountEl.textContent = normalCount;
                
                const eliteCountEl = document.getElementById('monster-elite-count');
                if (eliteCountEl) eliteCountEl.textContent = eliteCount;
                
                const bossCountEl = document.getElementById('monster-boss-count');
                if (bossCountEl) bossCountEl.textContent = bossCount;
                
                // 获取最近刷新的怪物信息
                const lastSpawnText = this.monsters.length > 0 ? 
                    `${this.monsters[this.monsters.length - 1].rank}${this.monsters[this.monsters.length - 1].type}` : '无';
                const lastSpawnEl = document.getElementById('monster-last-spawn');
                if (lastSpawnEl) lastSpawnEl.textContent = lastSpawnText;
                
                // 更新怪物列表计数
                const listCountEl = document.getElementById('monster-list-count');
                if (listCountEl) listCountEl.textContent = `(${this.monsters.length})`;
                
                // 如果列表展开了，更新列表内容
                const listContent = document.getElementById('monster-list-content');
                if (listContent && !listContent.classList.contains('collapsed')) {
                    this.updateMonsterListContent();
                }
            }
            
            /**
             * 切换怪物列表展开/收起状态 - UI交互系统
             * 控制怪物列表的展开和收起动画效果
             * 同步更新相关的UI元素状态和样式
             * 在展开时自动更新列表内容
             * 
             * 交互机制：
             * 1. 点击列表标题区域触发展开/收起
             * 2. 通过CSS类控制展开/收起状态
             * 3. 同步更新箭头图标方向
             * 4. 展开时高亮标题区域
             * 
             * 状态管理：
             * - collapsed类：控制列表内容显示/隐藏
             * - expanded类：控制标题区域高亮状态
             * - 展开时自动更新列表内容
             * - 收起时保留内容节省性能
             * 
             * DOM元素控制：
             * 1. 箭头元素：旋转动画指示状态
             * 2. 内容区域：显示/隐藏控制
             * 3. 标题区域：高亮状态控制
             * 
             * 性能优化：
             * - 只在展开时更新列表内容
             * - 收起时保留DOM结构
             * - 避免不必要的重排重绘
             */
            toggleMonsterList() {
                const arrow = document.getElementById('monster-list-arrow');
                const content = document.getElementById('monster-list-content');
                const header = document.querySelector('#monsters-tab .list-header');
                
                if (content && arrow && header) {
                    if (content.classList.contains('collapsed')) {
                        // 展开列表
                        content.classList.remove('collapsed');
                        header.classList.add('expanded');
                        this.updateMonsterListContent();
                    } else {
                        // 收起列表
                        content.classList.add('collapsed');
                        header.classList.remove('expanded');
                    }
                }
            }
            
            /**
             * 切换建筑列表展开/收起状态 - UI交互系统
             * 控制建筑详细列表的显示和隐藏
             * 点击标题时触发展开或收起动画
             * 同步更新箭头图标和标题样式
             * 
             * 功能说明：
             * 1. 点击展开时更新列表内容
             * 2. 切换箭头图标方向
             * 3. 更新标题区域样式
             * 4. 控制列表内容显示状态
             * 
             * 状态管理：
             * - 展开状态：显示详细建筑列表
             * - 收起状态：隐藏详细建筑列表
             * - 图标切换：向下箭头(收起) <-> 向上箭头(展开)
             * - 样式变化：普通背景 <-> 高亮背景
             */
            toggleBuildingList() {
                const arrow = document.getElementById('building-list-arrow');
                const content = document.getElementById('building-list-content');
                const header = document.querySelector('#buildings-tab .list-header');
                
                if (content && arrow && header) {
                    if (content.classList.contains('collapsed')) {
                        // 展开列表
                        content.classList.remove('collapsed');
                        header.classList.add('expanded');
                        this.updateBuildingListContent();
                    } else {
                        // 收起列表
                        content.classList.add('collapsed');
                        header.classList.remove('expanded');
                    }
                }
            }
            
            /**
             * 更新怪物列表内容 - UI列表系统
             * 动态生成并更新怪物列表的详细内容
             * 根据怪物稀有度和属性显示不同样式和信息
             * 支持空列表状态的特殊显示
             * 
             * 列表结构：
             * 1. 空列表状态：显示提示信息
             * 2. 非空列表：显示详细怪物信息
             * 3. 每项包含：属性、类型、等级、HP、位置
             * 4. 稀有度标识：普通/精英/首领/传说/神话
             * 5. 属性颜色：根据属性类型着色
             * 
             * 排序机制：
             * - 按稀有度降序排列
             * - 神话 > 传说 > 首领 > 精英 > 普通
             * - 相同稀有度保持原有顺序
             * 
             * 交互功能：
             * 1. 点击列表项打开详细信息模态框
             * 2. 稀有度颜色标识
             * 3. 属性颜色标识
             * 4. 位置信息显示
             * 
             * 性能优化：
             * 1. 列表更新前清空旧内容
             * 2. 空列表时显示特殊提示
             * 3. DOM操作最小化
             * 4. 元素复用减少创建开销
             * 
             * 数据展示：
             * - 怪物名称：属性+类型
             * - 等级信息：Lv.等级
             * - 生命值：当前/最大值
             * - 位置信息：坐标(x, y)
             * - 稀有度：颜色标识分类
             */
            updateMonsterListContent() {
                const listContent = document.getElementById('monster-list-content');
                const listEmpty = document.getElementById('monster-list-empty');
                
                if (!listContent) return;
                
                if (this.monsters.length === 0) {
                    if (listEmpty) listEmpty.style.display = 'block';
                    // 清空列表项
                    const existingItems = listContent.querySelectorAll('.list-item');
                    existingItems.forEach(item => item.remove());
                } else {
                    if (listEmpty) listEmpty.style.display = 'none';
                    
                    // 只有当怪物数量发生变化时才重新创建列表项，避免频繁刷新
                    const existingItems = listContent.querySelectorAll('.list-item');
                    if (existingItems.length !== this.monsters.length) {
                        // 清空旧的列表项
                        existingItems.forEach(item => item.remove());
                        
                        // 按稀有度排序（首领>精英>普通）
                        const sortedMonsters = [...this.monsters].sort((a, b) => {
                            const rankOrder = { '神话': 5, '传说': 4, '首领': 3, '精英': 2, '普通': 1 };
                            return (rankOrder[b.rank] || 0) - (rankOrder[a.rank] || 0);
                        });
                        
                        // 添加新的怪物列表项
                        sortedMonsters.forEach(monster => {
                            const listItem = document.createElement('div');
                            listItem.className = 'list-item';
                            listItem.onclick = () => this.showMonsterModal(monster);
                            
                            // 获取怪物属性颜色
                            const attributeColor = Config.MONSTER_ATTRIBUTES[monster.attribute]?.color || '#ffffff';
                            
                            listItem.innerHTML = `
                                <div class="list-item-main">
                                    <div class="list-item-title" style="color: ${attributeColor}">
                                        ${monster.attribute}${monster.type}
                                    </div>
                                    <div class="list-item-info">
                                        <span>Lv.${monster.level}</span>
                                        <span>HP: ${Math.floor(monster.hp)}/${monster.maxHp}</span>
                                        <span>位置: (${Math.floor(monster.x)}, ${Math.floor(monster.y)})</span>
                                    </div>
                                </div>
                                <div class="monster-rank rank-${monster.rank}">${monster.rank}</div>
                            `;
                            
                            listContent.appendChild(listItem);
                        });
                    }
                    // 如果数量相同，不需要更新，因为怪物信息相对静态
                }
            }

            /**
             * 更新建筑列表内容 - UI列表系统
             * 动态生成并更新建筑列表的详细内容
             * 根据建筑类型和等级显示不同样式和信息
             * 支持空列表状态的特殊显示
             * 
             * 列表结构：
             * 1. 空列表状态：显示提示信息
             * 2. 非空列表：显示详细建筑信息
             * 3. 每项包含：建筑名称、等级、收入、位置
             * 4. 建筑类型标识：不同建筑使用不同图标
             * 5. 等级颜色：根据建筑等级着色
             * 
             * 排序机制：
             * - 按建筑类型分组显示
             * - 同类型建筑按等级降序排列
             * - 未建造建筑显示在列表底部
             * 
             * 数据更新：
             * - 实时显示建筑等级和收入
             * - 位置信息显示建筑坐标
             * - 支持点击查看详情
             * - 空列表时显示提示信息
             * 
             * 性能优化：
             * - 只在列表展开时更新内容
             * - 缓存DOM元素引用
             * - 避免重复DOM操作
             * - 批量添加列表项
             */
            updateBuildingListContent() {
                this.debugLog('更新建筑列表，当前建筑数量:', this.buildings.length);
                const listContent = document.getElementById('building-list-content');
                const listEmpty = document.getElementById('building-list-empty');
                const listCountEl = document.getElementById('building-list-count');
                
                if (!listContent) return;
                
                // 更新列表计数
                if (listCountEl) {
                    listCountEl.textContent = `(${this.buildings.length})`;
                }
                
                // 清空旧的列表项
                const existingItems = listContent.querySelectorAll('.list-item');
                existingItems.forEach(item => item.remove());
                
                if (this.buildings.length === 0) {
                    if (listEmpty) listEmpty.style.display = 'block';
                } else {
                    if (listEmpty) listEmpty.style.display = 'none';
                    
                    // 按建筑类型分组
                    const buildingTypes = {};
                    this.buildings.forEach(building => {
                        if (!buildingTypes[building.type]) {
                            buildingTypes[building.type] = [];
                        }
                        buildingTypes[building.type].push(building);
                    });
                    
                    // 对每种建筑类型按等级排序
                    for (const type in buildingTypes) {
                        buildingTypes[type].sort((a, b) => b.level - a.level);
                    }
                    
                    // 添加新的建筑列表项
                    for (const type in buildingTypes) {
                        buildingTypes[type].forEach(building => {
                            const listItem = document.createElement('div');
                            listItem.className = 'list-item';
                            listItem.onclick = () => this.showBuildingModal(building);
                            
                            // 获取建筑图标
                            const buildingConfig = Config.BUILDINGS[building.type];
                            const iconClass = buildingConfig ? buildingConfig.icon : 'fas fa-building';
                            
                            // 计算建筑总收入（考虑称号加成）
                            const baseIncome = building.level * (building.income || 10);
                            const totalIncome = Math.floor(baseIncome * (1 + (this.titleEffects.buildingIncome || 0)));
                            
                            listItem.innerHTML = `
                                <div class="list-item-main">
                                    <div class="list-item-title">
                                        <i class="${iconClass}"></i> ${building.type}
                                    </div>
                                    <div class="list-item-info">
                                        <span>等级: ${building.level}</span>
                                        <span>收入: ${totalIncome}金/10秒</span>
                                        <span>位置: (${Math.floor(building.x)}, ${Math.floor(building.y)})</span>
                                    </div>
                                </div>
                                <div class="list-item-status status-alive">已建造</div>
                            `;
                            
                            listContent.appendChild(listItem);
                        });
                    }
                }
                this.debugLog('建筑列表更新完成');
            }

            /**
             * 更新经济页签
             */
            /**
             * 更新经济页签 - UI显示系统
             * 实时更新经济页签中的资源和收入统计数据
             * 包括金币、魅力值、建筑收入、税收等经济指标
             * 支持收入计算和统计显示
             * 
             * 经济数据：
             * 1. 金币数量：当前持有金币
             * 2. 魅力值：影响村庄吸引力
             * 3. 建筑收入：所有建筑产生的收入
             * 4. 税收收入：村民缴纳的税金
             * 5. 总收入：建筑收入+税收收入
             * 6. 总支出：当前支出统计（预留）
             * 
             * 收入计算：
             * - 建筑收入 = Σ(建筑等级 × 基础收入)
             * - 税收收入 = 村民数量 × 税率
             * - 总收入 = 建筑收入 + 税收收入
             * 
             * 性能优化：
             * 1. 缓存DOM元素引用
             * 2. 只在数值变化时更新
             * 3. 避免不必要的DOM操作
             * 4. 金币数值向下取整显示
             * 
             * 数据展示：
             * - 金币和魅力值实时显示
             * - 建筑收入显示/分钟
             * - 收入统计汇总显示
             * - 支出统计预留显示
             * 
             * DOM安全机制：
             * - 所有元素获取后检查存在性
             * - 避免对不存在元素的操作
             * - 稳定的文本内容更新
             * - 值变化检测避免冗余渲染
             */
            updateEconomyTab() {
                // 缓存DOM元素
                const elements = {
                    gold: document.getElementById('economy-gold'),
                    charm: document.getElementById('economy-charm'),
                    buildingIncome: document.getElementById('economy-building-income'),
                    taxIncome: document.getElementById('economy-tax-income'),
                    totalIncome: document.getElementById('economy-total-income'),
                    totalExpense: document.getElementById('economy-total-expense')
                };
                
                // 只更新存在的元素
                if (elements.gold) {
                    const goldValue = Math.floor(this.gold);
                    if (elements.gold.textContent != goldValue) {
                        elements.gold.textContent = goldValue;
                    }
                }
                
                if (elements.charm && elements.charm.textContent != this.charm) {
                    elements.charm.textContent = this.charm;
                }
                
                // 计算建筑收入 - 基于冒险者交互而不是自动产生
                // 显示当前周期的交互收入，而不是累计收入
                const buildingIncome = this.buildings.reduce((sum, building) => {
                    // 基于建筑类型和冒险者交互计算收入
                    const interactionIncome = building.interactionIncome || 0;
                    return sum + interactionIncome;
                }, 0);
                
                if (elements.buildingIncome) {
                    const incomeText = `${buildingIncome}/分钟`;
                    if (elements.buildingIncome.textContent != incomeText) {
                        elements.buildingIncome.textContent = incomeText;
                    }
                }
                
                if (elements.taxIncome && elements.taxIncome.textContent != this.taxRevenue) {
                    elements.taxIncome.textContent = this.taxRevenue;
                }
                
                const totalIncome = this.taxRevenue + buildingIncome;
                if (elements.totalIncome && elements.totalIncome.textContent != totalIncome) {
                    elements.totalIncome.textContent = totalIncome;
                }
                
                // 可以后续添加支出统计
                if (elements.totalExpense && elements.totalExpense.textContent != '0') {
                    elements.totalExpense.textContent = '0';
                }
            }
            
            /**
             * 更新副本页签 - UI显示系统
             * 实时更新副本页签中的队伍信息、统计数据和记录
             */
            updateDungeonTab() {
                // 更新副本统计数据
                const currentFloorElement = document.getElementById('dungeon-current-floor');
                const highestFloorElement = document.getElementById('dungeon-highest-floor');
                const teamPowerElement = document.getElementById('dungeon-team-power');
                
                if (currentFloorElement) {
                    currentFloorElement.textContent = this.activeDungeon ? this.activeDungeon.currentFloor : 0;
                }
                
                // 计算最高记录
                let highestFloor = 0;
                for (const adventurerId in this.dungeonRecords) {
                    if (this.dungeonRecords[adventurerId] > highestFloor) {
                        highestFloor = this.dungeonRecords[adventurerId];
                    }
                }
                if (highestFloorElement) {
                    highestFloorElement.textContent = highestFloor;
                }
                
                // 计算队伍实力评分
                const teamPower = this.calculateDungeonTeamPower();
                if (teamPowerElement) {
                    teamPowerElement.textContent = teamPower;
                }
                
                // 更新队伍显示
                this.updateDungeonTeamDisplay();
                
                // 更新副本记录
                this.updateDungeonRecordsDisplay();
            }
            
            /**
             * 计算副本队伍实力评分
             * @returns {number} 队伍实力评分
             */
            calculateDungeonTeamPower() {
                if (!this.dungeonTeamMembers || this.dungeonTeamMembers.length === 0) return 0;

                let totalPower = 0;
                let validCount = 0;
                for (const slot of this.dungeonTeamMembers) {
                    if (slot && slot.adventurerId) {
                        const adventurer = this.adventurers.find(a => a.id === slot.adventurerId);
                        if (adventurer) {
                            const p = Number(adventurer.powerScore || this.calculateAdventurerPowerScore(adventurer)) || 0;
                            totalPower += p;
                            validCount++;
                        }
                    }
                }

                if (validCount === 0) return 0;
                const avg = Math.floor(totalPower / validCount);
                return Number.isFinite(avg) ? avg : 0;
            }
            
            /**
             * 更新副本队伍显示
             */
            updateDungeonTeamDisplay() {
                const teamContainer = document.getElementById('dungeon-team-container');
                if (!teamContainer) return;
                
                // 清空容器
                teamContainer.innerHTML = '';
                
                // 重新创建所有槽位
                for (let i = 0; i < 4; i++) {
                    const slot = document.createElement('div');
                    slot.className = 'dungeon-team-slot';
                    slot.setAttribute('data-slot', i);
                    slot.dataset.index = i;  // 添加索引数据属性
                    
                    if (this.dungeonTeamMembers[i] && this.dungeonTeamMembers[i].adventurerId) {
                        // 槽位已分配
                        const adventurer = this.adventurers.find(a => a.id === this.dungeonTeamMembers[i].adventurerId);
                        if (adventurer) {
                            slot.classList.add('assigned');
                            slot.innerHTML = `
                                <div class="team-slot-icon">
                                    <i class="fas fa-user"></i>
                                </div>
                                <div class="team-slot-name">${adventurer.name}</div>
                                <div class="team-slot-label">Lv.${adventurer.level}</div>
                                <div class="team-slot-remove" data-index="${i}">
                                    <i class="fas fa-times"></i>
                                </div>
                            `;
                        } else {
                            // 冒险者不存在，显示空槽位
                            slot.innerHTML = `
                                <div class="team-slot-icon">
                                    <i class="fas fa-user-plus"></i>
                                </div>
                                <div class="team-slot-label">队员 ${i + 1}</div>
                            `;
                        }
                    } else {
                        // 空槽位
                        slot.innerHTML = `
                            <div class="team-slot-icon">
                                <i class="fas fa-user-plus"></i>
                            </div>
                            <div class="team-slot-label">队员 ${i + 1}</div>
                        `;
                    }
                    
                    teamContainer.appendChild(slot);
                }
                
                // 更新按钮状态
                const enterBtn = document.getElementById('dungeon-enter-btn');
                const resetBtn = document.getElementById('dungeon-reset-btn');
                
                if (enterBtn) {
                    enterBtn.disabled = this.dungeonTeamMembers.filter(t => t && t.adventurerId).length === 0;
                    enterBtn.onclick = () => this.enterDungeon();
                }
                
                if (resetBtn) {
                    resetBtn.onclick = () => this.resetDungeonTeam();
                }
            }
            
            /**
             * 选择副本队伍成员
             * @param {number} slotIndex - 队伍槽位索引
             */
            selectDungeonTeamMember(slotIndex) {
                // 显示冒险者选择界面
                this.showAdventurerSelectionForDungeon(slotIndex);
            }
            
            /**
             * 显示冒险者选择界面用于副本队伍
             * @param {number} slotIndex - 队伍槽位索引
             */
            showAdventurerSelectionForDungeon(slotIndex) {
                // 创建模态框内容
                let modalContent = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-users"></i> 选择冒险者 (队员 ${slotIndex + 1})</div>
                        <div class="adventurer-grid">
                `;
                
                // 过滤可选的冒险者（非死亡状态且未在其他队伍中）
                const availableAdventurers = this.adventurers.filter(adventurer => {
                    // 排除死亡状态的冒险者
                    if (adventurer.state === 'dead') return false;
                    
                    // 排除已经在队伍中的冒险者
                    const isInTeam = this.dungeonTeamMembers.some(team => {
                        // 确保team存在且有adventurerId属性
                        return team && team.adventurerId && team.adventurerId === adventurer.id;
                    });
                    
                    return !isInTeam;
                });
                
                if (availableAdventurers.length === 0) {
                    modalContent += '<div class="log-entry">没有可选的冒险者</div>';
                } else {
                    availableAdventurers.forEach(adventurer => {
                        const classIcon = this.getClassIcon(adventurer.class);
                        const classColor = this.getClassColor(adventurer.class);
                        modalContent += `
                            <div class="adventurer-card" data-adventurer-id="${adventurer.id}" data-slot-index="${slotIndex}">
                                <div class="adventurer-header">
                                    <div class="adventurer-icon ${classColor}">
                                        <i class="${classIcon}"></i>
                                    </div>
                                    <div class="adventurer-name ${classColor}">${adventurer.name}</div>
                                    <div class="adventurer-level">Lv.${adventurer.level}</div>
                                </div>
                                <div class="adventurer-stats">
                                    <div class="stat-item">
                                        <span>职业</span>
                                        <span>${adventurer.class}</span>
                                    </div>
                                    <div class="stat-item">
                                        <span>实力</span>
                                        <span>${Math.floor(adventurer.powerScore || this.calculateAdventurerPowerScore(adventurer))}</span>
                                    </div>
                                    <div class="stat-item">
                                        <span>状态</span>
                                        <span>${adventurer.state}</span>
                                    </div>
                                </div>
                            </div>
                        `;
                    });
                }
                
                modalContent += `
                        </div>
                        <div style="text-align: center; margin-top: 20px;">
                            <button id="cancel-dungeon-selection" class="dungeon-action-btn">
                                <i class="fas fa-times"></i> 取消
                            </button>
                        </div>
                    </div>
                `;
                
                // 显示模态框
                const modal = document.getElementById('modal');
                const modalContentElement = document.getElementById('modal-content');
                if (modal && modalContentElement) {
                    modalContentElement.innerHTML = modalContent;
                    modal.style.display = 'block';
                    
                    // 添加冒险者卡片点击事件 - 使用 onclick 替换 addEventListener，避免重复绑定
                    modalContentElement.onclick = (e) => {
                        const card = e.target.closest('.adventurer-card');
                        if (card) {
                            // getAttribute 返回字符串，强制转换为数字以便与冒险者 id 类型匹配
                            const adventurerId = Number(card.getAttribute('data-adventurer-id'));
                            const slotIndex = parseInt(card.getAttribute('data-slot-index'));
                            this.assignAdventurerToDungeonTeam(slotIndex, adventurerId);
                            modal.style.display = 'none';
                            return;
                        }
                        const cancelBtn = e.target.closest('#cancel-dungeon-selection');
                        if (cancelBtn) {
                            modal.style.display = 'none';
                        }
                    };
                }
            }
            
            /**
             * 分配冒险者到副本队伍
             * @param {number} slotIndex - 队伍槽位索引
             * @param {string} adventurerId - 冒险者ID
             */
            assignAdventurerToDungeonTeam(slotIndex, adventurerId) {
                // 强制将 adventurerId 转为数字，避免字符串/数字比较导致的问题
                const id = Number(adventurerId);

                // 防止重复分配：如果该冒险者已经在队伍中，则忽略
                const alreadyInTeam = this.dungeonTeamMembers.some(team => team && team.adventurerId === id);
                if (alreadyInTeam) {
                    this.addLogEntry('该冒险者已在队伍中，不能重复选择', 'warning');
                    return;
                }

                // 确保队伍数组足够大
                while (this.dungeonTeamMembers.length <= slotIndex) {
                    this.dungeonTeamMembers.push(null);
                }

                // 分配冒险者到指定槽位（存储为数字）
                this.dungeonTeamMembers[slotIndex] = {
                    adventurerId: id,
                    assignedTime: Date.now()
                };

                // 只更新队伍显示，而不是整个标签页
                this.updateDungeonTeamDisplay();
            }
            
            /**
             * 从副本队伍中移除冒险者
             * @param {number} slotIndex - 队伍槽位索引
             */
            removeAdventurerFromDungeonTeam(slotIndex) {
                if (this.dungeonTeamMembers[slotIndex]) {
                    this.dungeonTeamMembers[slotIndex] = null;
                    this.updateDungeonTeamDisplay();
                }
            }
            
            /**
             * 重置副本队伍
             */
            resetDungeonTeam() {
                this.dungeonTeamMembers = [];
                this.updateDungeonTab();
                this.addLogEntry('副本队伍已重置', 'info');
            }
            
            /**
             * 进入副本
             */
            enterDungeon() {
                // 检查队伍是否有效
                const validTeamMembers = this.dungeonTeamMembers.filter(t => t && t.adventurerId);
                if (validTeamMembers.length === 0) {
                    this.showNotification('请先选择至少一名冒险者组成队伍', 'error');
                    return;
                }

                // 使用 createDungeonTeam 创建完整的队伍对象（包含成员引用）并加入 dungeonTeams
                const adventurerIds = validTeamMembers.map(t => Number(t.adventurerId));
                const team = this.createDungeonTeam(adventurerIds);
                if (!team) {
                    this.showNotification('创建队伍失败', 'error');
                    return;
                }

                // 将当前激活的副本指向该队伍对象，方便UI读取
                this.activeDungeon = team;

                this.addLogEntry(`队伍进入副本，开始挑战第1层`, 'success');
                this.updateDungeonTab();

                // 启动副本运行器（模拟战斗与推进）
                this.startDungeonRun(team);
            }
            
            /**
             * 计算副本怪物等级
             * @returns {number} 怪物等级
             */
            calculateDungeonMonsterLevel() {
                // 计算队伍平均等级
                let totalLevel = 0;
                let validMembers = 0;
                
                for (const team of this.dungeonTeamMembers) {
                    if (team && team.adventurerId) {
                        const adventurer = this.adventurers.find(a => a.id === team.adventurerId);
                        if (adventurer) {
                            totalLevel += adventurer.level;
                            validMembers++;
                        }
                    }
                }
                
                const avgLevel = validMembers > 0 ? Math.floor(totalLevel / validMembers) : 1;
                return avgLevel;
            }
            
            /**
             * 更新副本记录显示
             */
            updateDungeonRecordsDisplay() {
                const recordsContainer = document.getElementById('dungeon-records');
                if (!recordsContainer) return;
                
                // 获取记录条目
                const records = [];
                for (const adventurerId in this.dungeonRecords) {
                    const adventurer = this.adventurers.find(a => a.id === adventurerId);
                    if (adventurer) {
                        records.push({
                            adventurerName: adventurer.name,
                            highestFloor: this.dungeonRecords[adventurerId],
                            class: adventurer.class
                        });
                    }
                }
                
                // 按最高层数排序
                records.sort((a, b) => b.highestFloor - a.highestFloor);
                
                if (records.length === 0) {
                    recordsContainer.innerHTML = '<p>暂无副本记录</p>';
                } else {
                    let recordsHtml = '';
                    records.forEach(record => {
                        const classColor = this.getClassColor(record.class);
                        recordsHtml += `
                            <div class="record-entry">
                                <div class="record-date">
                                    <span class="${classColor}">${record.adventurerName}</span>
                                </div>
                                <div class="record-details">
                                    最高层数: ${record.highestFloor}层
                                </div>
                            </div>
                        `;
                    });
                    recordsContainer.innerHTML = recordsHtml;
                }
            }
            
            /**
             * 更新建筑页签 - UI显示系统
             * 实时更新建筑页签中的建筑列表和统计信息
             * 包括建筑数量、类型分布等核心统计数据
             * 
             * 显示内容：
             * 1. 建筑数量统计（当前总数）
             * 2. 各类型建筑数量分布
             * 3. 建筑收入统计
             * 4. 建筑列表计数更新
             * 
             * 数据更新：
             * - 实时统计建筑总数
             * - 分类统计各类型建筑
             * - 计算建筑总收入
             * - 更新列表计数显示
             * 
             * 性能优化：
             * - 只在页签激活时更新
             * - 缓存DOM元素引用
             * - 避免不必要的DOM操作
             * - 值变化检测避免冗余渲染
             * 
             * DOM安全机制：
             * - 所有元素获取后检查存在性
             * - 避免对不存在元素的操作
             * - 稳定的文本内容更新
             */
            updateBuildingsTab() {
                // 更新建筑列表计数
                const listCountEl = document.getElementById('building-list-count');
                if (listCountEl) {
                    listCountEl.textContent = `(${this.buildings.length})`;
                }
                
                // 如果建筑列表是展开状态，更新列表内容
                const listContent = document.getElementById('building-list-content');
                if (listContent && !listContent.classList.contains('collapsed')) {
                    this.updateBuildingListContent();
                }
            }

            /**
             * 切换游戏暂停状态 - 游戏控制系统
             * 控制游戏主循环的暂停和继续
             * 同步更新暂停按钮的显示状态和样式
             * 提供直观的视觉反馈
             * 
             * 控制机制：
             * 1. 切换暂停状态布尔值
             * 2. 更新暂停按钮文本和图标
             * 3. 根据状态改变按钮背景色
             * 4. 暂停时停止主循环更新
             * 5. 继续时恢复主循环更新
             * 
             * 视觉反馈：
             * - 暂停状态：绿色背景 + 播放图标 + "继续"文本
             * - 运行状态：蓝色背景 + 暂停图标 + "暂停"文本
             * - 图标使用Font Awesome字体图标
             * 
             * 状态管理：
             * - isPaused属性控制游戏循环
             * - 按钮文本动态切换
             * - 背景色状态区分
             * - 图标与文本同步变化
             * 
             * UI元素控制：
             * - 暂停按钮元素获取和更新
             * - innerHTML内容动态设置
             * - style属性直接修改背景色
             * - Font Awesome图标嵌入支持
             */
            togglePause() {
                this.isPaused = !this.isPaused;
                const btn = document.getElementById('pause-btn');
                if (this.isPaused) {
                    btn.innerHTML = '<i class="fas fa-play"></i> 继续';
                    btn.style.background = '#2ecc71';
                } else {
                    btn.innerHTML = '<i class="fas fa-pause"></i> 暂停';
                    btn.style.background = '#3498db';
                }
            }

            /**
             * 创建建筑方法
             * 根据建筑类型和坐标创建新的建筑对象
             * @param {string} type - 建筑类型
             * @param {number} x - 建筑X坐标
             * @param {number} y - 建筑Y坐标
             * @returns {boolean} 创建成功返回true，失败返回false
             */
            createBuilding(type, x, y) {
                // 获取建筑成本配置
                const cost = Config.BUILDING_COSTS[type];
                if (!cost) return false;
                
                // 检查资源是否足够 - 判断玩家是否有足够的金币和魅力值建造建筑
                const canAfford = this.gold >= cost.gold && this.charm >= (cost.charm || 0);
                
                if (canAfford) {
                    // 扣除建造成本
                    this.gold -= cost.gold;
                    if (cost.charm) this.charm -= cost.charm;

                    // 创建建筑对象 - 包含建筑的所有属性和状态信息
                    const building = {
                        id: Date.now() + Math.random(),           // 建筑唯一标识符
                        type,                                     // 建筑类型
                        x,                                        // 建筑X坐标
                        y,                                        // 建筑Y坐标
                        level: 1,                                 // 建筑等级，默认为1级
                        width: this.getBuildingSize(type).width,  // 建筑宽度
                        height: this.getBuildingSize(type).height,// 建筑高度
                        income: this.calculateBuildingIncome(type, 1), // 建筑收入
                        interactionCount: 0,                      // 交互计数器
                        interactionIncome: 0,                     // 交互收入
                        maxLevel: this.getBuildingMaxLevel(type), // 建筑最高等级
                        upgradeCost: this.calculateUpgradeCost(type, 1), // 升级费用
                        efficiency: 1.0,                          // 建筑效率，默认100%
                        lastUpgrade: Date.now(),                  // 上次升级时间
                        employees: [],                            // 雇员列表
                        maxEmployees: this.getMaxEmployees(type), // 最大雇员数量
                        specialEffects: this.getBuildingSpecialEffects(type), // 特殊效果
                        condition: 'excellent',                   // 建筑状态：优秀、良好、一般、较差、损坏
                        maintenanceCost: Math.floor(cost.gold * 0.02), // 每日维护成本（建造费用的2%）
                        constructionTime: Date.now(),             // 建造时间
                        isActive: true                            // 是否激活状态
                    };

                    // 将新建筑添加到建筑列表中
                    this.buildings.push(building);
                    
                    // 更新任务进度 - 如果有相关建筑任务，则更新进度
                    this.updateQuestProgress(type);
                    
                    // 添加日志记录 - 记录建造事件到游戏日志
                    this.addLogEntry(`建造了${type} (Lv.1)`, 'success');
                    
                    // 更新资源显示 - 刷新界面上的资源数值
                    this.updateResourceDisplay();
                    // 更新魅力值 - 根据建筑重新计算村庄魅力值
                    this.updateCharmFromBuildings();
                    
                    return true;
                } else {
                    // 资源不足，显示错误信息
                    const missingGold = Math.max(0, cost.gold - this.gold);
                    const missingCharm = Math.max(0, (cost.charm || 0) - this.charm);
                    let message = '资源不足！需要：';
                    
                    if (missingGold > 0) {
                        message += `${missingGold}金币`;
                    }
                    if (missingCharm > 0) {
                        if (missingGold > 0) message += '、';
                        message += `${missingCharm}魅力值`;
                    }
                    
                    this.showNotification(message, 'error');
                }
                return false;
            }
            
            /**
             * 获取建筑尺寸方法
             * 根据建筑类型返回对应的宽度和高度
             * @param {string} type - 建筑类型
             * @returns {Object} 包含width和height属性的对象
             */
            getBuildingSize(type) {
                // 定义各种建筑类型的尺寸配置
                const sizes = {
                    '旅馆': { width: 80, height: 60 },      // 旅馆：80x60像素
                    '饭店': { width: 70, height: 50 },      // 饭店：70x50像素
                    '武器店': { width: 75, height: 55 },    // 武器店：75x55像素
                    '防具店': { width: 75, height: 55 },    // 防具店：75x55像素
                    '冒险公会': { width: 100, height: 80 }, // 冒险公会：100x80像素
                    '市集': { width: 90, height: 70 },      // 市集：90x70像素
                    '魔法塔': { width: 60, height: 120 },   // 魔法塔：60x120像素（高塔型建筑）
                    '铁匠铺': { width: 85, height: 65 },    // 铁匠铺：85x65像素
                    '炼金术师': { width: 70, height: 60 },  // 炼金术师：70x60像素
                    '图书馆': { width: 110, height: 90 },   // 图书馆：110x90像素（大型建筑）
                    '精灵树': { width: 50, height: 100 },   // 精灵树：50x100像素（竖直型建筑）
                    '竞技场': { width: 120, height: 100 },  // 竞技场：120x100像素（最大型建筑）
                    '寺庙': { width: 90, height: 80 },      // 寺庙：90x80像素
                    '守卫塔': { width: 40, height: 100 },   // 守卫塔：40x100像素（细长型建筑）
                    '仓库': { width: 100, height: 60 },     // 仓库：100x60像素
                    '研究所': { width: 120, height: 80 }   // 研究所：120x80像素
                };
                // 返回指定建筑类型的尺寸，如果未找到则返回默认尺寸80x60
                return sizes[type] || { width: 80, height: 60 };
            }
            
            /**
             * 获取建筑最高等级方法
             * 根据建筑类型返回该建筑可以达到的最高等级
             * @param {string} type - 建筑类型
             * @returns {number} 建筑最高等级
             */
            getBuildingMaxLevel(type) {
                // 定义各种建筑类型的最高等级配置
                const maxLevels = {
                    '旅馆': 10,      // 旅馆：最高等级10级
                    '饭店': 10,      // 饭店：最高等级10级
                    '武器店': 15,    // 武器店：最高等级15级
                    '防具店': 15,    // 防具店：最高等级15级
                    '冒险公会': 20,  // 冒险公会：最高等级20级（重要建筑）
                    '市集': 12,      // 市集：最高等级12级
                    '魔法塔': 25,    // 魔法塔：最高等级25级（魔法建筑）
                    '铁匠铺': 20,    // 铁匠铺：最高等级20级
                    '炼金术师': 18,  // 炼金术师：最高等级18级
                    '图书馆': 15,    // 图书馆：最高等级15级
                    '精灵树': 30,    // 精灵树：最高等级30级（自然建筑）
                    '竞技场': 15,    // 竞技场：最高等级15级
                    '寺庙': 10,      // 寺庙：最高等级10级
                    '守卫塔': 20,    // 守卫塔：最高等级20级
                    '仓库': 5,       // 仓库：最高等级5级（功能性建筑）
                    '研究所': 25     // 研究所：最高等级25级（科技建筑）
                };
                // 返回指定建筑类型的最高等级，如果未找到则返回默认等级10级
                return maxLevels[type] || 10;
            }
            
            /**
             * 获取职业图标
             * @param {string} className - 职业名称
             * @returns {string} Font Awesome图标类名
             */
            getClassIcon(className) {
                const icons = {
                    '战士': 'fas fa-sword',
                    '法师': 'fas fa-wand-magic-sparkles',
                    '游侠': 'fas fa-bow-arrow',
                    '牧师': 'fas fa-hands-praying',
                    '盗贼': 'fas fa-mask',
                    '骑士': 'fas fa-shield',
                    '术士': 'fas fa-skull',
                    '德鲁伊': 'fas fa-leaf',
                    '刺客': 'fas fa-knife',
                    '圣骑士': 'fas fa-cross'
                };
                return icons[className] || 'fas fa-user';
            }
            
            /**
             * 获取职业颜色类
             * @param {string} className - 职业名称
             * @returns {string} CSS颜色类名
             */
            getClassColor(className) {
                const colors = {
                    '战士': 'class-warrior',
                    '法师': 'class-mage',
                    '游侠': 'class-ranger',
                    '牧师': 'class-priest',
                    '盗贼': 'class-rogue',
                    '骑士': 'class-knight',
                    '术士': 'class-warlock',
                    '德鲁伊': 'class-druid',
                    '刺客': 'class-assassin',
                    '圣骑士': 'class-paladin'
                };
                return colors[className] || 'class-default';
            }
            
            /**
             * 计算建筑收入方法
             * 根据建筑类型和等级计算该建筑的每分钟收入
             * @param {string} type - 建筑类型
             * @param {number} level - 建筑等级
             * @returns {number} 建筑每分钟收入金币数
             */
            /**
             * 计算建筑收入 - 经济系统
             * 根据建筑类型和等级计算每10秒的金币收入
             * 采用指数增长模型，等级越高收益越大
             * 支持不同类型建筑的基础收入配置
             * 
             * 收入配置：
             * - 旅馆：15金币/分钟基础收入
             * - 饭店：12金币/分钟基础收入
             * - 武器店/防具店：25金币/分钟基础收入
             * - 冒险公会：40金币/分钟基础收入
             * - 市集：30金币/分钟基础收入
             * - 魔法塔：60金币/分钟基础收入
             * - 铁匠铺：45金币/分钟基础收入
             * - 炼金术师：50金币/分钟基础收入
             * - 图书馆：20金币/分钟基础收入
             * - 精灵树：10金币/分钟基础收入
             * - 竞技场：80金币/分钟基础收入
             * - 寺庙：35金币/分钟基础收入
             * - 守卫塔：5金币/分钟基础收入
             * - 仓库/研究所：0金币/分钟
             * 
             * 收入计算：
             * - 公式：基础收入 × 等级 × (1 + 等级 × 0.1)
             * - 指数增长：等级越高收益增长越快
             * - 默认值：未配置建筑类型使用10金币基础收入
             * - 时间单位：每10秒计算一次收入
             * 
             * 经济平衡：
             * - 高收入建筑升级成本也更高
             * - 功能性建筑提供间接收益
             * - 收入增长鼓励持续投资
             * - 避免初期过快积累金币
             * 
             * @param {string} type - 建筑类型
             * @param {number} level - 建筑等级
             * @returns {number} 每10秒的金币收入
             */
            /**
             * 计算建筑收入 - 经济系统
             * 根据建筑类型和等级计算每分钟产生的金币收入
             * 采用加速增长模型，等级越高收入增长越快
             * 支持不同类型建筑的差异化收入配置
             * 
             * 收入计算公式：
             * 建筑收入 = 基础收入 × 等级 × (1 + 等级 × 0.1)
             * 随着等级提升，收入增长会加速（等级越高收益越大）
             * 
             * 建筑收入配置：
             * - 旅馆：15金币/分钟（基础服务建筑）
             * - 饭店：12金币/分钟（基础服务建筑）
             * - 武器店：25金币/分钟（商业建筑）
             * - 防具店：25金币/分钟（商业建筑）
             * - 冒险公会：40金币/分钟（重要建筑）
             * - 市集：30金币/分钟（商业中心）
             * - 魔法塔：60金币/分钟（高收入建筑）
             * - 铁匠铺：45金币/分钟（工艺建筑）
             * - 炼金术师：50金币/分钟（高级商业建筑）
             * - 图书馆：20金币/分钟（文化建筑）
             * - 精灵树：10金币/分钟（自然建筑）
             * - 竞技场：80金币/分钟（最高收入建筑）
             * - 寺庙：35金币/分钟（宗教建筑）
             * - 守卫塔：5金币/分钟（防御建筑）
             * - 仓库：0金币/分钟（功能性建筑）
             * - 研究所：0金币/分钟（科技建筑）
             * 
             * 增长机制：
             * - 线性等级加成：收入与等级成正比
             * - 加速增长因子：等级越高收益增幅越大
             * - 差异化配置：不同类型建筑基础收入不同
             * - 默认值处理：未配置建筑使用10金币基础值
             * 
             * 经济平衡设计：
             * - 高级建筑提供更高基础收入
             * - 功能性建筑专注于特殊功能而非收入
             * - 收入增长鼓励玩家升级建筑
             * - 避免收入过高破坏游戏平衡
             * 
             * @param {string} type - 建筑类型
             * @param {number} level - 建筑等级
             * @returns {number} 每分钟金币收入
             */
            calculateBuildingIncome(type, level) {
                // 定义各种建筑类型的基础收入配置（每分钟金币数）
                const baseIncomes = {
                    '旅馆': 15,      // 旅馆：基础15金币/分钟
                    '饭店': 12,      // 饭店：基础12金币/分钟
                    '武器店': 25,    // 武器店：基础25金币/分钟
                    '防具店': 25,    // 防具店：基础25金币/分钟
                    '冒险公会': 40,  // 冒险公会：基础40金币/分钟（重要建筑）
                    '市集': 30,      // 市集：基础30金币/分钟
                    '魔法塔': 60,    // 魔法塔：基础60金币/分钟（高收入建筑）
                    '铁匠铺': 45,    // 铁匠铺：基础45金币/分钟
                    '炼金术师': 50,  // 炼金术师：基础50金币/分钟
                    '图书馆': 20,    // 图书馆：基础20金币/分钟
                    '精灵树': 10,    // 精灵树：基础10金币/分钟（自然建筑）
                    '竞技场': 80,    // 竞技场：基础80金币/分钟（最高收入）
                    '寺庙': 35,      // 寺庙：基础35金币/分钟
                    '守卫塔': 5,     // 守卫塔：基础5金币/分钟（防御建筑）
                    '仓库': 0,       // 仓库：0金币/分钟（功能性建筑）
                    '研究所': 0      // 研究所：0金币/分钟（科技建筑）
                };
                // 计算建筑收入：基础收入 × 等级 × (1 + 等级 × 0.1)
                // 随着等级提升，收入增长会加速（等级越高收益越大）
                return (baseIncomes[type] || 10) * level * (1 + level * 0.1);
            }
            
            /**
             * 计算建筑升级费用 - 经济系统
             * 根据建筑类型和当前等级计算升级到下一级所需的金币
             * 采用指数增长模型，等级越高升级费用越昂贵
             * 防止玩家过快升级建筑保持游戏平衡
             * 
             * 费用计算公式：
             * 升级费用 = 基础费用 × 0.5 × 1.4^当前等级
             * 使用指数增长模型，等级越高升级费用越昂贵
             * 
             * 指数增长特点：
             * - 底数1.4表示每级费用增长40%
             * - 0.5系数降低初始升级成本
             * - 向下取整保证费用为整数金币
             * - 基础费用从Config.BUILDING_COSTS获取
             * 
             * 经济平衡设计：
             * - 升级成本随等级指数增长
             * - 高级建筑升级需要更多资源
             * - 鼓励玩家平衡发展建筑
             * - 避免过快升级破坏游戏平衡
             * - 与收入增长保持合理比例
             * 
             * 成本增长机制：
             * - 初期成本相对较低便于起步
             * - 中期成本快速增长形成挑战
             * - 后期成本昂贵需要资源积累
             * - 不同建筑基础成本差异化
             * 
             * 参数说明：
             * - type：建筑类型，用于获取基础费用
             * - currentLevel：当前等级，影响费用计算
             * - 返回值：升级到下一级所需金币数
             * 
             * @param {string} type - 建筑类型
             * @param {number} currentLevel - 建筑当前等级
             * @returns {number} 升级到下一级所需的金币数
             */
            calculateUpgradeCost(type, currentLevel) {
                // 获取建筑的基础建造费用（金币）
                const baseCost = Config.BUILDING_COSTS[type].gold;
                // 计算升级费用：基础费用 × 0.5 × 1.4^当前等级
                // 使用指数增长模型，等级越高升级费用越昂贵
                return Math.floor(baseCost * 0.5 * Math.pow(1.4, currentLevel - 1)); // 修复：使用currentLevel-1避免费用过高
            }
            
            /**
             * 获取建筑最大雇员数方法
             * 根据建筑类型返回该建筑可以雇佣的最大雇员数量
             * @param {string} type - 建筑类型
             * @returns {number} 建筑最大雇员数量
             */
            getMaxEmployees(type) {
                // 定义各种建筑类型的最大雇员数量配置
                const employees = {
                    '旅馆': 3,       // 旅馆：最多3名雇员
                    '饭店': 4,       // 饭店：最多4名雇员
                    '武器店': 2,     // 武器店：最多2名雇员
                    '防具店': 2,     // 防具店：最多2名雇员
                    '冒险公会': 5,   // 冒险公会：最多5名雇员
                    '市集': 6,       // 市集：最多6名雇员
                    '魔法塔': 2,     // 魔法塔：最多2名雇员
                    '铁匠铺': 3,     // 铁匠铺：最多3名雇员
                    '炼金术师': 2,   // 炼金术师：最多2名雇员
                    '图书馆': 3,     // 图书馆：最多3名雇员
                    '精灵树': 1,     // 精灵树：最多1名雇员
                    '竞技场': 4,     // 竞技场：最多4名雇员
                    '寺庙': 2,       // 寺庙：最多2名雇员
                    '守卫塔': 1,     // 守卫塔：最多1名雇员
                    '仓库': 1,       // 仓库：最多1名雇员
                    '研究所': 8      // 研究所：最多8名雇员（科研建筑）
                };
                // 返回指定建筑类型的最大雇员数量，如果未找到则返回默认1名
                return employees[type] || 1;
            }
            
            /**
             * 获取建筑特殊效果方法
             * 根据建筑类型返回该建筑提供的特殊效果
             * @param {string} type - 建筑类型
             * @returns {Object|null} 建筑特殊效果对象或null（无特殊效果）
             */
            getBuildingSpecialEffects(type) {
                // 定义各种建筑类型的特殊效果配置
                const effects = {
                    '图书馆': { 
                        expBonus: 0.1, 
                        description: '提升全体经验获取10%' 
                    },  // 图书馆：提供10%全体经验加成
                    '精灵树': { 
                        mpRegen: 0.05, 
                        description: '每秒恢复5%最大魔法值' 
                    },  // 精灵树：每秒恢复5%最大魔法值
                    '寺庙': { 
                        blessing: 1, 
                        description: '提供神圣祝福，提升全属性' 
                    },  // 寺庙：提供神圣祝福，提升全属性
                    '守卫塔': { 
                        protection: 1, 
                        description: '防御怪物进攻，减少死亡率' 
                    },  // 守卫塔：防御怪物进攻，减少冒险者死亡率
                    '研究所': { 
                        research: 1, 
                        description: '解锁新技术和升级' 
                    },  // 研究所：解锁新技术和升级选项
                    '魔法塔': { 
                        enchant: 1, 
                        description: '可以对装备进行附魔' 
                    },  // 魔法塔：可以对装备进行附魔
                    '铁匠铺': { 
                        upgrade: 1, 
                        description: '可以升级和修理装备' 
                    },  // 铁匠铺：可以升级和修理装备
                    '炼金术师': { 
                        potion: 1, 
                        description: '制作各种药剂' 
                    },  // 炼金术师：可以制作各种药剂
                    '竞技场': { 
                        training: 1, 
                        description: '冒险者可以进行训练和PVP' 
                    }   // 竞技场：冒险者可以进行训练和PVP对战
                };
                // 返回指定建筑类型的特殊效果，如果无特殊效果则返回null
                return effects[type] || null;
            }
            
            /**
             * 更新魅力值方法
             * 根据所有建筑提供的魅力加成重新计算村庄总魅力值
             */
            updateCharmFromBuildings() {
                // 从初始魅力值开始计算
                let totalCharm = Config.INITIAL_CHARM;
                // 遍历所有建筑，累加每个建筑提供的魅力加成
                this.buildings.forEach(building => {
                    const charmBonus = this.getBuildingCharmBonus(building);
                    totalCharm += charmBonus;
                });
                // 更新村庄总魅力值
                this.charm = totalCharm;
            }
            
            /**
             * 获取建筑魅力加成方法
             * 根据建筑类型、等级和效率计算该建筑提供的魅力值加成
             * @param {Object} building - 建筑对象
             * @returns {number} 建筑提供的魅力值加成
             */
            getBuildingCharmBonus(building) {
                // 定义各种建筑类型的基础魅力加成配置
                const charmBonuses = {
                    '旅馆': 2,       // 旅馆：基础魅力加成2点
                    '饭店': 1,       // 饭店：基础魅力加成1点
                    '武器店': 1,     // 武器店：基础魅力加成1点
                    '防具店': 1,     // 防具店：基础魅力加成1点
                    '冒险公会': 5,   // 冒险公会：基础魅力加成5点
                    '市集': 3,       // 市集：基础魅力加成3点
                    '魔法塔': 8,     // 魔法塔：基础魅力加成8点
                    '铁匠铺': 3,     // 铁匠铺：基础魅力加成3点
                    '炼金术师': 4,   // 炼金术师：基础魅力加成4点
                    '图书馆': 6,     // 图书馆：基础魅力加成6点
                    '精灵树': 10,    // 精灵树：基础魅力加成10点
                    '竞技场': 8,     // 竞技场：基础魅力加成8点
                    '寺庙': 15,      // 寺庙：基础魅力加成15点（最高）
                    '守卫塔': 2,     // 守卫塔：基础魅力加成2点
                    '仓库': 0,       // 仓库：基础魅力加成0点
                    '研究所': 12     // 研究所：基础魅力加成12点
                };
                // 获取建筑类型的基础魅力加成
                const baseCharm = charmBonuses[building.type] || 0;
                // 计算实际魅力加成：基础加成 × 建筑等级 × 建筑效率
                return Math.floor(baseCharm * building.level * building.efficiency);
            }
            
            /**
             * 检查建筑重叠
             * @param {string} type - 建筑类型
             * @param {number} x - X坐标
             * @param {number} y - Y坐标
             * @returns {boolean} 是否有重叠
             */
            /**
             * 检查建筑重叠方法
             * 检查在指定位置建造新建筑是否会与现有建筑重叠
             * @param {string} type - 新建筑类型
             * @param {number} x - 新建筑X坐标
             * @param {number} y - 新建筑Y坐标
             * @returns {boolean} 如果重叠返回true，否则返回false
             */
            checkBuildingOverlap(type, x, y) {
                // 在文字游戏中，我们不需要检查建筑重叠
                // 因为在文字游戏中不需要考虑建筑的具体位置
                // 允许建造多个相同类型的建筑
                return false;
            }
            
            /**
             * 优化冒险者寻找建筑的逻辑，选择最近的可用建筑
             * @param {string} buildingType - 建筑类型
             * @param {Object} adventurer - 冒险者对象
             * @returns {Object|null} 最近的建筑或null
             */
            findNearestBuilding(buildingType, adventurer) {
                const suitableBuildings = this.buildings.filter(b => b.type === buildingType && b.isActive);
                
                if (suitableBuildings.length === 0) return null;
                
                if (suitableBuildings.length === 1) return suitableBuildings[0];
                
                // 找到最近的建筑
                let nearestBuilding = null;
                let shortestDistance = Infinity;
                
                suitableBuildings.forEach(building => {
                    const dx = building.x + building.width/2 - adventurer.x;
                    const dy = building.y + building.height/2 - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance < shortestDistance) {
                        shortestDistance = distance;
                        nearestBuilding = building;
                    }
                });
                
                this.debugLog(`${adventurer.name} 找到最近的${buildingType}，距离${Math.floor(shortestDistance)}像素`);
                return nearestBuilding;
            }
            
            /**
             * 应急食物系统 - 当冒险者无法支付饭店费用时的应急措施
             * @param {Object} adventurer - 冒险者对象
             */
            tryEmergencyFood(adventurer) {
                // 根据冒险者的状态调整找到食物的几率
                let findChance = 0.6; // 基础几率提高刷60%
                
                // 受伤状态下降低找到食物的能力
                if (adventurer.hp < adventurer.maxHp * 0.3) {
                    findChance *= 0.7;
                }
                
                // 饥饿越严重，越容易找到食物（求生本能）
                if (adventurer.hunger <= 10) {
                    findChance += 0.3;
                }
                
                if (Math.random() < findChance) {
                    // 成功找到少量食物
                    const emergencyFood = Math.floor(adventurer.maxHunger * (0.25 + Math.random() * 0.15)); // 25%-40%的饥饿值恢复
                    adventurer.hunger = Math.min(adventurer.maxHunger, adventurer.hunger + emergencyFood);
                    
                    const foodTypes = ['野生浆果', '昆虫', '野菜', '藘菇', '水果', '小动物'];
                    const foundFood = foodTypes[Math.floor(Math.random() * foodTypes.length)];
                    
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 找到了一些${foundFood}，恢复了${emergencyFood}点饥饿值`);
                    
                    // 应急食物有小几率恢复少量生命值
                    if (Math.random() < 0.3) {
                        const minorHeal = Math.floor(adventurer.maxHp * 0.05);
                        adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + minorHeal);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${foundFood}含有营养，也恢复了${minorHeal}点生命值`);
                    }
                } else {
                    // 未找到食物，但不放弃希望
                    const encouragement = ['继续寻找中...', '不要放弃希望', '一定会找到食物的', '再试试其他地方'];
                    const message = encouragement[Math.floor(Math.random() * encouragement.length)];
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 未找到可食用的食物，${message}`);
                }
            }
            
            /**
             * 慈善援助系统 - 村长给贫困的冒险者提供援助
             */
            provideCharityAid() {
                const poorAdventurers = this.adventurers.filter(adv => 
                    adv.state !== 'dead' && adv.gold < 20 && adv.hunger < 50
                );
                
                if (poorAdventurers.length > 0) {
                    poorAdventurers.forEach(adventurer => {
                        const aid = 15; // 给予一些基本援助金币
                        adventurer.gold += aid;
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 收到村长的慈善援助：${aid}金币`);
                    });
                    
                    this.showNotification(`慈善援助：向${poorAdventurers.length}名贫困冒险者提供了援助`, 'success');
                }
            }
            
            /**
             * 紧急援助系统 - 对急需帮助的冒险者提供立即援助
             */
            provideEmergencyAid() {
                const emergencyAdventurers = this.adventurers.filter(adv => {
                    return adv.state !== 'dead' && (
                        // 生命值极低且饥饿的冒险者
                        (adv.hp <= adv.maxHp * 0.15 && adv.hunger <= Config.HUNGER_CRITICAL && adv.gold < 30) ||
                        // 或者饥饿到极限且没有金币的冒险者
                        (adv.hunger <= 10 && adv.gold < 20)
                    );
                });
                
                if (emergencyAdventurers.length > 0) {
                    emergencyAdventurers.forEach(adventurer => {
                        // 紧急援助金币
                        const emergencyGold = 25;
                        adventurer.gold += emergencyGold;
                        
                        // 紧急食物援助
                        const emergencyFood = Math.floor(adventurer.maxHunger * 0.3);
                        adventurer.hunger = Math.min(adventurer.maxHunger, adventurer.hunger + emergencyFood);
                        
                        // 紧急医疗援助
                        if (adventurer.hp <= adventurer.maxHp * 0.15) {
                            const emergencyHeal = Math.floor(adventurer.maxHp * 0.2);
                            adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + emergencyHeal);
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 接受村长紧急医疗援助，恢复${emergencyHeal}点生命值`);
                        }
                        
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 收到村长紧急援助：${emergencyGold}金币和${emergencyFood}点饥饿值`);
                        
                        // 给予短暂的安全保护，避免立即又陷入危险
                        adventurer.combatCooldown = Math.max(adventurer.combatCooldown || 0, Date.now() + 15000);
                    });
                    
                    this.showNotification(`紧急援助：救助了${emergencyAdventurers.length}名危险冒险者`, 'error');
                }
            }

            showNotification(message, type = 'info') {
                // 记录到游戏日志
                this.addLogEntry(message, type);
                
                // 简单的通知实现，可以根据需要扩展
                const notification = document.createElement('div');
                notification.textContent = message;
                notification.style.cssText = `
                    position: fixed;
                    top: 80px;
                    right: 20px;
                    background: ${type === 'error' ? '#e74c3c' : type === 'success' ? '#2ecc71' : '#3498db'};
                    color: white;
                    padding: 10px 15px;
                    border-radius: 5px;
                    z-index: 1000;
                    font-size: 14px;
                    box-shadow: 0 4px 8px rgba(0,0,0,0.3);
                `;
                
                document.body.appendChild(notification);
                
                // 3秒后自动移除
                setTimeout(() => {
                    if (notification && notification.parentNode) {
                        notification.parentNode.removeChild(notification);
                    }
                }, 3000);
            }
            
            /**
             * 开始建筑放置模式
             * @param {string} buildingType - 建筑类型
             */
            /**
             * 开始建筑放置模式 - 建筑系统
             * 启动指定建筑类型的放置流程
             * 执行资源检查和放置模式初始化
             * 在文字游戏模式下提供信息提示
             * 
             * 启动流程：
             * 1. 验证建筑类型有效性
             * 2. 检查玩家资源是否充足
             * 3. 资源不足时计算缺失数量
             * 4. 显示资源不足提示信息
             * 5. 资源充足时进入放置模式
             * 6. 文字游戏模式下显示提示
             * 
             * 资源验证：
             * - 金币检查：gold >= cost.gold
             * - 魅力值检查：charm >= cost.charm
             * - 支持无魅力值消耗的建筑
             * - 精确计算缺失资源数量
             * 
             * 错误处理：
             * - 未知建筑类型：显示错误通知
             * - 资源不足：显示详细缺失信息
             * - 多资源不足：组合显示所有缺失
             * 
             * 放置模式：
             * - active标志：标识放置模式状态
             * - buildingType：记录要放置的建筑类型
             * - previewBuilding：预览建筑对象（未使用）
             * 
             * 文字游戏适配：
             * - 显示无法建造的提示信息
             * - 引导用户查看建筑页签
             * - 保持接口一致性
             * 
             * @param {string} buildingType - 要放置的建筑类型
             */
            startBuildingPlacement(buildingType) {
                const cost = Config.BUILDING_COSTS[buildingType];
                if (!cost) {
                    this.showNotification(`未知建筑类型: ${buildingType}`, 'error');
                    return;
                }
                
                // 检查资源是否足够
                const canAfford = this.gold >= cost.gold && this.charm >= (cost.charm || 0);
                
                // 在文字游戏中，直接显示建筑信息而不是进入放置模式
                this.showBuildingTypeInfo(buildingType);
                
                // 文字游戏模式下无需更新Canvas样式
            }
            
            /**
             * 取消建筑放置模式
             */
            /**
             * 取消建筑放置模式 - 建筑系统
             * 退出当前的建筑放置模式状态
             * 重置放置模式相关数据
             * 显示取消操作的通知
             * 
             * 取消流程：
             * 1. 检查放置模式是否处于激活状态
             * 2. 重置放置模式对象为非激活状态
             * 3. 显示取消操作的通知信息
             * 4. 界面自动回到正常操作模式
             * 
             * 状态管理：
             * - active标志重置为false
             * - 清除建筑类型信息
             * - 清除预览建筑对象
             * - 保持对象结构一致性
             * 
             * 用户反馈：
             * - 显示"已取消建筑放置"通知
             * - 使用info级别提示信息
             * - 提供操作确认反馈
             * 
             * 安全检查：
             * - 放置模式存在性检查
             * - 激活状态检查
             * - 避免对非激活状态操作
             * - 防止重复取消操作
             */
            cancelBuildingPlacement() {
                if (this.placementMode && this.placementMode.active) {
                    this.placementMode = { active: false };
                    this.showNotification('已取消建筑放置', 'info');
                }
            }
            
            
            
            /**
             * 显示建筑信息面板
             * @param {Object} building - 建筑对象
             * @param {Event} event - 鼠标事件
             */
            showBuildingInfo(building, event) {
                this.debugLog(`点击了建筑: ${building.type} Lv.${building.level}`);
                
                // 可以在这里添加建筑信息面板的显示逻辑
                // 例如：建筑等级、收益、升级费用等
                const info = `
                    建筑：${building.type}\n
                    等级：${building.level}/${building.maxLevel}\n
                    收益：${building.income}金币/分钟\n
                    状态：${this.getBuildingConditionText(building.condition)}\n
                    升级费用：${building.upgradeCost}金币
                `;
                
                if (confirm(info + '\n\n是否要升级该建筑？')) {
                    this.upgradeBuildingLevel(building);
                }
            }
            
            /**
             * 获取建筑状态文本
             * @param {string} condition - 建筑状态
             * @returns {string} 中文状态描述
             */
            /**
             * 获取建筑状态文本方法
             * 将建筑状态代码转换为中文描述文本
             * @param {string} condition - 建筑状态代码
             * @returns {string} 中文状态描述
             */
            getBuildingConditionText(condition) {
                // 定义建筑状态代码与中文描述的映射关系
                const conditionMap = {
                    'excellent': '优秀',    // 优秀状态
                    'good': '良好',         // 良好状态
                    'normal': '一般',       // 一般状态
                    'poor': '较差',         // 较差状态
                    'broken': '损坏'        // 损坏状态
                };
                // 返回对应的状态文本，如果未找到则返回'未知'
                return conditionMap[condition] || '未知';
            }
            
            /**
             * 升级建筑等级
             * @param {Object} building - 建筑对象
             */
            /**
             * 升级建筑等级方法
             * 将指定建筑升级到下一级，消耗金币并更新相关属性
             * @param {Object} building - 要升级的建筑对象
             */
            upgradeBuildingLevel(building) {
                // 检查建筑是否已达到最高等级
                if (building.level >= building.maxLevel) {
                    this.showNotification('建筑已达到最高等级！', 'info');
                    return;
                }
                
                // 获取升级费用
                const upgradeCost = building.upgradeCost;
                
                // 检查玩家是否有足够的金币进行升级
                if (this.gold >= upgradeCost) {
                    // 扣除升级费用
                    this.gold -= upgradeCost;
                    // 增加建筑等级
                    building.level++;
                    // 重新计算建筑收入（升级后收入增加）
                    building.income = this.calculateBuildingIncome(building.type, building.level);
                    // 重新计算下一次升级费用（升级后费用增加）
                    building.upgradeCost = this.calculateUpgradeCost(building.type, building.level);
                    // 记录升级时间
                    building.lastUpgrade = Date.now();
                    
                    // 显示升级成功通知
                    this.showNotification(`${building.type}升级成功！现在是${building.level}级`, 'success');
                    // 添加日志记录
                    this.addLogEntry(`${building.type}升级到${building.level}级`, 'success');
                    // 更新资源显示
                    this.updateResourceDisplay();
                } else {
                    // 金币不足，计算还需要多少金币
                    const needed = upgradeCost - this.gold;
                    this.showNotification(`金币不足，还需要${needed}金币`, 'error');
                }
            }
            
            /**
             * 更新建筑按钮状态，根据资源情况显示不同样式
             */
            /**
             * 更新建筑按钮状态方法
             * 根据玩家当前资源情况更新建筑按钮的可购买状态样式
             */
            /**
             * 更新建筑按钮状态 - UI状态系统
             * 根据玩家当前资源动态更新建筑按钮的可购买状态
             * 为可购买和不可购买的建筑添加不同样式
             * 实现实时资源状态反馈
             * 
             * 状态分类：
             * 1. 可购买状态：资源充足时显示
             * 2. 不可购买状态：资源不足时显示
             * 3. 成本不足标识：具体资源不足时显示
             * 
             * 更新机制：
             * 1. 遍历所有建筑按钮元素
             * 2. 获取建筑类型和成本配置
             * 3. 检查玩家资源是否充足
             * 4. 根据结果添加对应CSS类
             * 5. 更新成本显示元素样式
             * 
             * 样式控制：
             * - affordable类：资源充足时的按钮样式
             * - unaffordable类：资源不足时的按钮样式
             * - insufficient类：成本显示元素的不足样式
             * 
             * 资源检查：
             * - 金币检查：gold >= cost.gold
             * - 魅力值检查：charm >= cost.charm
             * - 支持无魅力值消耗的建筑
             * 
             * 性能优化：
             * - 批量更新所有建筑按钮
             * - 状态类重置避免样式冲突
             * - 元素存在性检查确保安全
             * - 避免不必要的DOM操作
             */
            updateBuildingButtonStates() {
                // 遍历所有建筑按钮元素
                document.querySelectorAll('.building-item').forEach(item => {
                    // 获取建筑类型
                    const buildingType = item.getAttribute('data-building');
                    // 获取建筑成本配置
                    const cost = Config.BUILDING_COSTS[buildingType];
                    
                    if (cost) {
                        // 检查玩家是否有足够的资源购买该建筑
                        const canAfford = this.gold >= cost.gold && this.charm >= (cost.charm || 0);
                        // 获取成本显示元素
                        const costElement = item.querySelector('.building-cost');
                        
                        // 移除之前的状态类（重置样式）
                        item.classList.remove('affordable', 'unaffordable');
                        if (costElement) {
                            costElement.classList.remove('insufficient');
                        }
                        
                        // 根据资源情况添加新的状态类
                        if (canAfford) {
                            // 资源足够，添加可购买样式
                            item.classList.add('affordable');
                        } else {
                            // 资源不足，添加不可购买样式
                            item.classList.add('unaffordable');
                            if (costElement) {
                                costElement.classList.add('insufficient');
                            }
                        }
                    }
                });
            }
            
            /**
             * 显示建筑类型信息 - 建筑信息系统
             * 在文字游戏中显示建筑类型的基本信息和功能说明
             * 为玩家提供详细的建筑功能介绍和成本信息
             * 支持直接建造建筑功能
             * 
             * 信息内容：
             * 1. 建筑名称和图标
             * 2. 基本功能描述
             * 3. 建造成本（金币和魅力值）
             * 4. 建筑效果和收益
             * 5. 升级潜力说明
             * 
             * 显示方式：
             * - 在建筑信息面板显示详细信息
             * - 提供建造按钮
             * - 支持交互式查看详情
             * 
             * 数据来源：
             * - Config.BUILDING_COSTS：建造成本配置
             * - Config.BUILDING_FUNCTIONS：功能配置
             * - Config.BUILDING_EFFECTS：效果配置
             * 
             * @param {string} buildingType - 建筑类型名称
             */
            showBuildingTypeInfo(buildingType) {
                // 获取建筑成本配置
                const cost = Config.BUILDING_COSTS[buildingType];
                // 获取建筑功能配置
                const func = Config.BUILDING_FUNCTIONS[buildingType];
                
                if (!cost || !func) {
                    this.showNotification(`未找到建筑类型: ${buildingType}`, 'error');
                    return;
                }
                
                // 检查资源是否足够
                const canAfford = this.gold >= cost.gold && this.charm >= (cost.charm || 0);
                
                // 构建建筑信息面板内容
                let html = `
                    <div style="text-align: center; margin-bottom: 15px;">
                        <h3 style="color: #f39c12; margin: 0 0 10px 0;">${buildingType}</h3>
                    </div>
                    <div style="margin-bottom: 15px;">
                        <div><strong>功能:</strong> ${func.effect}</div>
                        <div><strong>建造费用:</strong> ${cost.gold}金币`;
                
                if (cost.charm > 0) {
                    html += `, ${cost.charm}魅力值`;
                }
                
                html += `</div>`;
                
                // 添加功能效果说明
                switch(func.type) {
                    case 'rest':
                        html += `<div><strong>效果:</strong> 恢复生命值 +${func.value}</div>`;
                        break;
                    case 'food':
                        html += `<div><strong>效果:</strong> 恢复饥饿值 +${func.value}</div>`;
                        break;
                    case 'shop':
                        html += `<div><strong>效果:</strong> 提供装备交易服务</div>`;
                        break;
                    case 'guild':
                        html += `<div><strong>效果:</strong> 提供任务板服务</div>`;
                        break;
                    case 'market':
                        html += `<div><strong>效果:</strong> 提供通用交易服务</div>`;
                        break;
                    case 'magic':
                        html += `<div><strong>效果:</strong> 提供附魔服务</div>`;
                        break;
                    case 'craft':
                        html += `<div><strong>效果:</strong> 提供装备升级服务</div>`;
                        break;
                    case 'alchemy':
                        html += `<div><strong>效果:</strong> 提供药水制作服务</div>`;
                        break;
                    case 'knowledge':
                        html += `<div><strong>效果:</strong> 经验获取加成 +${Math.floor(func.value * 100)}%</div>`;
                        break;
                    case 'nature':
                        html += `<div><strong>效果:</strong> 全属性加成 +${Math.floor(func.value * 100)}%</div>`;
                        break;
                    case 'combat':
                        html += `<div><strong>效果:</strong> 战斗经验加成 +${Math.floor(func.value * 100)}%</div>`;
                        break;
                    case 'spiritual':
                        html += `<div><strong>效果:</strong> 魔法值恢复 +${func.value}</div>`;
                        break;
                    case 'defense':
                        html += `<div><strong>效果:</strong> 村庄防护功能</div>`;
                        break;
                    case 'storage':
                        html += `<div><strong>效果:</strong> 背包容量扩展 +${func.value}</div>`;
                        break;
                    case 'research':
                        html += `<div><strong>效果:</strong> 研究速度加成 +${Math.floor(func.value * 100)}%</div>`;
                        break;
                    default:
                        html += `<div><strong>效果:</strong> ${func.effect}</div>`;
                }
                
                html += `</div>`;
                
                // 添加建造按钮
                if (canAfford) {
                    html += `
                        <div style="text-align: center; margin-top: 15px;">
                            <button id="build-building-btn" data-building-type="${buildingType}"
                                    style="background: #27ae60; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer;">
                                建造建筑
                            </button>
                        </div>`;
                } else {
                    html += `
                        <div style="text-align: center; margin-top: 15px;">
                            <button disabled 
                                    style="background: #7f8c8d; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: not-allowed;">
                                资源不足
                            </button>
                        </div>`;
                }
                
                // 显示建筑信息面板
                const panel = document.getElementById('building-info-panel');
                const content = document.getElementById('building-info-content');
                if (panel && content) {
                    content.innerHTML = html;
                    panel.style.display = 'block';
                    
                    // 为建造按钮添加事件监听器
                    // 使用setTimeout确保DOM更新完成后再绑定事件
                    setTimeout(() => {
                        const buildBtn = document.getElementById('build-building-btn');
                        if (buildBtn) {
                            // 移除所有现有的事件监听器
                            const newBtn = buildBtn.cloneNode(true);
                            buildBtn.parentNode.replaceChild(newBtn, buildBtn);
                            
                            // 添加新的点击事件监听器
                            newBtn.addEventListener('click', (e) => {
                                e.preventDefault();
                                e.stopPropagation();
                                this.debugLog('点击建造按钮:', buildingType);
                                const type = newBtn.getAttribute('data-building-type');
                                if (type) {
                                    this.buildBuildingFromInfo(type);
                                } else {
                                    this.debugLog('建筑类型未定义');
                                }
                            });
                        }
                    }, 100);
                }
            }
            
            /**
             * 从信息面板建造建筑 - 建筑系统
             * 在文字游戏中通过建筑信息面板直接建造建筑
             * 自动分配建筑位置并处理建造逻辑
             * 
             * 建造流程：
             * 1. 验证建筑类型和资源
             * 2. 自动分配建筑位置（避免重叠）
             * 3. 调用createBuilding函数创建建筑
             * 4. 更新UI显示和资源状态
             * 5. 关闭信息面板
             * 
             * 位置分配策略：
             * - 在村庄区域内随机分配位置
             * - 检查位置重叠避免冲突
             * - 确保建筑在可视区域内
             * 
             * @param {string} buildingType - 要建造的建筑类型
             */
            buildBuildingFromInfo(buildingType) {
                this.debugLog('开始建造建筑:', buildingType);
                // 获取建筑成本配置
                const cost = Config.BUILDING_COSTS[buildingType];
                if (!cost) {
                    this.showNotification(`未知建筑类型: ${buildingType}`, 'error');
                    return;
                }
                
                // 检查资源是否足够
                const canAfford = this.gold >= cost.gold && this.charm >= (cost.charm || 0);
                if (!canAfford) {
                    const missingGold = Math.max(0, cost.gold - this.gold);
                    const missingCharm = Math.max(0, (cost.charm || 0) - this.charm);
                    let message = '资源不足！需要：';
                    
                    if (missingGold > 0) {
                        message += `${missingGold}金币`;
                    }
                    if (missingCharm > 0) {
                        if (missingGold > 0) message += '、';
                        message += `${missingCharm}魅力值`;
                    }
                    
                    this.showNotification(message, 'error');
                    return;
                }
                
                // 在文字游戏中，我们不需要考虑建筑的具体位置
                // 但为了保持一致性，我们仍然传递坐标参数
                const x = 0;  // 在文字游戏中，位置不重要
                const y = 0;  // 在文字游戏中，位置不重要
                
                // 调用createBuilding函数创建建筑
                // createBuilding函数内部会处理建筑类型重复检查和资源扣除
                this.debugLog('调用createBuilding函数');
                const success = this.createBuilding(buildingType, x, y);
                this.debugLog('createBuilding返回结果:', success);
                
                if (success) {
                    this.showNotification(`成功建造了${buildingType}！`, 'success');
                    // 关闭建筑信息面板
                    const panel = document.getElementById('building-info-panel');
                    if (panel) {
                        panel.style.display = 'none';
                    }
                    // 更新建筑列表
                    this.debugLog('更新建筑列表');
                    this.updateBuildingListContent();
                    // 更新资源显示
                    this.updateResourceDisplay();
                } else {
                    // 如果建造失败，退还资源
                    this.gold += cost.gold;
                    if (cost.charm) {
                        this.charm += cost.charm;
                    }
                    this.debugLog('建筑创建失败');
                    this.showNotification(`建造${buildingType}失败！`, 'error');
                }
            }
            
            /**
             * 绘制建筑放置预览
             */
            /**
             * 绘制建筑放置预览 - 建筑系统
             * 在图形模式下绘制建筑放置的实时预览效果
             * 根据鼠标位置显示建筑放置预览和可行性
             * 提供视觉反馈指示放置是否可行
             * 
             * 绘制条件：
             * 1. 放置模式必须处于激活状态
             * 2. 存在有效的鼠标位置信息
             * 3. 游戏处于图形显示模式
             * 
             * 预览功能：
             * - 实时跟随鼠标位置显示
             * - 显示建筑大小和形状
             * - 颜色区分放置可行性
             *   - 绿色：可以放置
             *   - 红色：无法放置（重叠冲突）
             * - 显示建筑名称标识
             * 
             * 技术实现：
             * - 使用Canvas API绘制预览
             * - 透明度设置避免遮挡背景
             * - 文本居中显示建筑名称
             * - 状态保存和恢复确保不影响其他绘制
             * 
             * 碰撞检测：
             * - 调用checkBuildingOverlap方法
             * - 检查与现有建筑的重叠
             * - 实时计算放置可行性
             * 
             * 视觉效果：
             * - 70%透明度的预览框
             * - 中心对齐的建筑名称
             * - 颜色编码的状态指示
             * - 中文字体支持
             */
            renderBuildingPlacementPreview() {
                if (!this.placementMode || !this.placementMode.active) return;
                
                // 获取鼠标位置（用于工具提示定位）
                if (this.mouseX !== undefined && this.mouseY !== undefined) {
                    const buildingSize = this.getBuildingSize(this.placementMode.buildingType);
                    const x = this.mouseX - buildingSize.width / 2;
                    const y = this.mouseY - buildingSize.height / 2;
                    
                    // 检查是否可以放置
                    const canPlace = !this.checkBuildingOverlap(this.placementMode.buildingType, x, y);
                    
                    // 绘制预览建筑
                    this.ctx.save();
                    this.ctx.globalAlpha = 0.7;
                    this.ctx.fillStyle = canPlace ? '#2ecc71' : '#e74c3c';
                    this.ctx.fillRect(x, y, buildingSize.width, buildingSize.height);
                    
                    // 绘制建筑名称
                    this.ctx.globalAlpha = 1;
                    this.ctx.fillStyle = '#ffffff';
                    this.ctx.font = '12px Microsoft YaHei, sans-serif';
                    this.ctx.textAlign = 'center';
                    this.ctx.fillText(this.placementMode.buildingType, x + buildingSize.width/2, y + buildingSize.height/2);
                    this.ctx.textAlign = 'left';
                    this.ctx.restore();
                }
            }
            
            // 任务系统方法
            initializeQuests() {
                // 初始化第一个任务
                this.activeQuests = ['first_adventurer'];
                this.questProgress = {
                    'first_adventurer': 0,
                    'defeat_monsters': 0,
                    'build_inn': 0,
                    'collect_equipment': 0,
                    'rich_town': 0
                };
            }
            
            /**
             * 初始化研究系统
             * 设置研究树和初始解锁状态
             */
            initializeResearch() {
                // 初始化研究进度，所有研究项目默认未解锁且未研究
                for (const researchId in Config.RESEARCH_TREE) {
                    const research = Config.RESEARCH_TREE[researchId];
                    this.researchProgress[researchId] = {
                        unlocked: research.prerequisites.length === 0, // 没有前置条件的自动解锁
                        researched: false,
                        progress: 0
                    };
                }
                
                // 清空当前研究和研究效果
                this.activeResearch = null;
                this.researchEffects = {};
            }
            
            /**
             * 更新研究显示界面
             * 刷新研究面板中的研究项目列表
             */
            /**
             * 更新研究面板显示 - UI显示系统
             * 动态生成并更新研究面板的内容显示
             * 根据研究项目状态显示不同样式和信息
             * 支持研究进度条和状态标识
             * 
             * 显示状态：
             * 1. 已完成：绿色标识，显示完成状态
             * 2. 研究中：蓝色标识，显示进度条
             * 3. 可研究：正常显示，可点击开始
             * 4. 未解锁：灰色标识，显示问号
             * 
             * 研究项目信息：
             * - 研究名称：项目唯一标识
             * - 研究描述：功能说明文本
             * - 消耗资源：金币消耗数量
             * - 当前状态：状态文本标识
             * - 进度条：研究中项目的进度
             * 
             * 交互功能：
             * 1. 点击可研究项目开始研究
             * 2. 进度条实时更新显示
             * 3. 状态颜色区分显示
             * 4. 未解锁项目隐藏信息
             * 
             * 性能优化：
             * 1. 字符串拼接生成HTML内容
             * 2. 一次性更新整个列表内容
             * 3. 元素存在性检查确保安全
             * 4. 避免重复DOM查询操作
             * 
             * 数据展示：
             * - 研究项目按配置顺序显示
             * - 进度条宽度按百分比计算
             * - 状态文本动态生成
             * - 未解锁项目显示占位信息
             */
            updateResearchDisplay() {
                const researchList = document.getElementById('research-list');
                if (!researchList) return;
                
                let html = '';
                
                for (const researchId in Config.RESEARCH_TREE) {
                    const research = Config.RESEARCH_TREE[researchId];
                    const progress = this.researchProgress[researchId] || { unlocked: false, researched: false, progress: 0 };
                    
                    if (progress.unlocked) {
                        const status = progress.researched ? '已完成' : 
                                     (this.activeResearch === researchId ? '研究中...' : '可研究');
                        const cssClass = progress.researched ? 'research-item research-completed' :
                                        (this.activeResearch === researchId ? 'research-item research-active' : 'research-item research-available');
                        
                        html += `
                            <div class="${cssClass}" data-research="${researchId}" onclick="game.startResearch('${researchId}')">
                                <div class="research-name">${research.name}</div>
                                <div class="research-desc">${research.description}</div>
                                <div class="research-cost">消耗：${research.cost.gold}金币</div>
                                <div class="research-status">${status}</div>
                                ${this.activeResearch === researchId ? `<div class="research-progress-bar"><div class="research-progress-fill" style="width: ${(progress.progress / research.cost.time) * 100}%"></div></div>` : ''}
                            </div>
                        `;
                    } else {
                        html += `
                            <div class="research-item research-locked">
                                <div class="research-name">???</div>
                                <div class="research-desc">需要前置研究</div>
                            </div>
                        `;
                    }
                }
                
                researchList.innerHTML = html;
            }
            
            /**
             * 开始研究项目 - 研究系统
             * 启动指定研究项目的研发过程
             * 执行前置条件检查和资源扣除
             * 更新UI显示和游戏状态
             * 
             * 启动条件：
             * 1. 研究项目必须存在且已解锁
             * 2. 研究项目未完成
             * 3. 当前无正在进行的研究
             * 4. 拥有足够金币资源
             * 
             * 执行流程：
             * 1. 验证研究项目有效性
             * 2. 检查前置条件
             * 3. 验证资源充足性
             * 4. 扣除研究消耗
             * 5. 设置当前研究项目
             * 6. 重置研究进度
             * 7. 显示启动通知
             * 8. 更新相关UI显示
             * 
             * 资源管理：
             * - 金币消耗：直接扣除研究费用
             * - 进度重置：清零当前进度
             * - 状态更新：设置为活跃研究
             * 
             * 错误处理：
             * - 项目不存在：直接返回
             * - 已完成研究：显示错误通知
             * - 未解锁研究：显示错误通知
             * - 研究冲突：显示错误通知
             * - 资源不足：显示错误通知
             * 
             * UI反馈：
             * - 启动通知：显示研究项目名称
             * - 资源更新：刷新金币显示
             * - 研究面板：更新状态显示
             * 
             * @param {string} researchId - 要开始研究的项目ID
             */
            startResearch(researchId) {
                const research = Config.RESEARCH_TREE[researchId];
                const progress = this.researchProgress[researchId] || { unlocked: false, researched: false, progress: 0 };
                
                if (!research) return;
                
                // 检查是否已研究或未解锁
                if (progress.researched || !progress.unlocked) {
                    this.showNotification('无法研究此项目', 'error');
                    return;
                }
                
                // 检查是否有正在研究的项目
                if (this.activeResearch) {
                    this.showNotification('已有正在研究的项目', 'error');
                    return;
                }
                
                // 检查资源
                if (this.gold < research.cost.gold) {
                    this.showNotification('金币不足', 'error');
                    return;
                }
                
                // 扣除资源
                this.gold -= research.cost.gold;
                
                // 开始研究
                this.activeResearch = researchId;
                progress.progress = 0;
                
                this.showNotification(`开始研究：${research.name}`);
                this.updateResourceDisplay();
                this.updateResearchDisplay();
            }
            
            /**
             * 更新研究进度 - 研究系统
             * 持续更新当前活跃研究项目的进度
             * 根据时间增量计算研究进展
             * 检测研究完成条件并触发完成流程
             * 
             * 更新机制：
             * 1. 检查是否存在活跃研究
             * 2. 验证研究项目有效性
             * 3. 累加时间增量到进度
             * 4. 检查是否达到完成条件
             * 5. 完成时触发完成处理
             * 
             * 进度计算：
             * - 进度累加：progress += deltaTime
             * - 完成条件：progress >= cost.time
             * - 时间单位：毫秒
             * 
             * 触发条件：
             * - 无活跃研究：直接返回
             * - 研究无效：直接返回
             * - 进度未满：仅更新进度
             * - 进度完成：触发完成流程
             * 
             * 性能优化：
             * - 早期返回避免无效计算
             * - 对象存在性验证
             * - 最小化不必要的操作
             * 
             * 系统集成：
             * - 与游戏主循环同步
             * - 调用研究完成处理
             * - 依赖研究配置数据
             * 
             * @param {number} deltaTime - 距离上次更新的时间增量（毫秒）
             */
            updateResearchProgress(deltaTime) {
                if (!this.activeResearch) return;
                
                const research = Config.RESEARCH_TREE[this.activeResearch];
                const progress = this.researchProgress[this.activeResearch] || { unlocked: false, researched: false, progress: 0 };
                
                if (!research) return;
                
                // 更新进度
                progress.progress += deltaTime;
                
                // 检查是否完成
                if (progress.progress >= research.cost.time) {
                    this.completeResearch(this.activeResearch);
                }
            }
            
            /**
             * 完成研究项目 - 研究系统
             * 处理研究项目的完成流程
             * 应用研究效果并解锁后续研究
             * 提供完成反馈和通知
             * 
             * 完成流程：
             * 1. 标记研究项目为已完成
             * 2. 设置进度为完成状态
             * 3. 清除当前活跃研究
             * 4. 应用研究效果属性
             * 5. 解锁后续可研究项目
             * 6. 显示完成通知和成就
             * 7. 记录到游戏日志
             * 8. 更新研究面板显示
             * 
             * 效果应用：
             * - 累加研究效果数值
             * - 支持多种效果类型
             * - 效果值可叠加累积
             * - 存储在研究效果对象中
             * 
             * 后续解锁：
             * - 检查所有后续研究
             * - 验证前置条件满足
             * - 解锁符合条件的项目
             * - 显示解锁通知
             * 
             * 反馈机制：
             * - 成就系统通知
             * - 游戏日志记录
             * - 研究面板更新
             * - 视觉和文本反馈
             * 
             * 状态管理：
             * - 研究状态标记
             * - 进度值设置
             * - 活跃研究清除
             * - 效果属性应用
             * 
             * @param {string} researchId - 要完成的研究项目ID
             */
            completeResearch(researchId) {
                const research = Config.RESEARCH_TREE[researchId];
                const progress = this.researchProgress[researchId] || { unlocked: false, researched: false, progress: 0 };
                
                if (!research) return;
                
                // 标记为已完成
                progress.researched = true;
                progress.progress = research.cost.time;
                
                // 清除当前研究
                this.activeResearch = null;
                
                // 应用研究效果
                for (const effect in research.effects) {
                    this.researchEffects[effect] = (this.researchEffects[effect] || 0) + research.effects[effect];
                }
                
                // 解锁后续研究
                this.unlockFollowUpResearch(researchId);
                
                this.showAchievement(`研究完成！`, `完成了研究：${research.name}`);
                this.addLogEntry(`完成了研究：${research.name}`, 'success');
                this.updateResearchDisplay();
            }
            
            /**
             * 解锁后续研究项目 - 研究系统
             * 根据已完成研究解锁后续可研究项目
             * 验证前置条件并解锁符合条件的项目
             * 提供解锁反馈和通知
             * 
             * 解锁机制：
             * 1. 遍历所有研究项目配置
             * 2. 跳过已解锁的项目
             * 3. 检查项目是否依赖已完成研究
             * 4. 验证所有前置条件是否满足
             * 5. 满足条件时解锁项目
             * 6. 显示解锁通知
             * 
             * 前置条件验证：
             * - 检查项目是否包含已完成研究
             * - 验证所有前置研究是否已完成
             * - 使用every方法确保全部满足
             * - 支持多个前置条件
             * 
             * 解锁条件：
             * - 项目未被解锁
             * - 包含已完成研究作为前置
             * - 所有前置研究已完成
             * 
             * 反馈机制：
             * - 解锁通知显示项目名称
             * - 研究面板会自动更新显示
             * - 玩家可立即开始新研究
             * 
             * 性能优化：
             * - 已解锁项目直接跳过
             * - 前置条件不匹配直接跳过
             * - 最小化不必要的验证
             * - 高效的数组遍历
             * 
             * @param {string} completedResearchId - 刚刚完成的研究项目ID
             */
            unlockFollowUpResearch(completedResearchId) {
                for (const researchId in Config.RESEARCH_TREE) {
                    const research = Config.RESEARCH_TREE[researchId];
                    const progress = this.researchProgress[researchId] || { unlocked: false, researched: false, progress: 0 };
                    
                    // 检查是否已解锁
                    if (progress.unlocked) continue;
                    
                    // 检查前置条件
                    if (research.prerequisites.includes(completedResearchId)) {
                        // 检查所有前置条件是否都已完成
                        const allPrerequisitesMet = research.prerequisites.every(prereqId => 
                            this.researchProgress[prereqId]?.researched
                        );
                        
                        if (allPrerequisitesMet) {
                            progress.unlocked = true;
                            this.showNotification(`解锁新研究：${research.name}`);
                        }
                    }
                }
            }
            
            /**
             * 更新任务显示界面
             * 刷新任务面板中的任务列表
             */
            updateQuestDisplay() {
                const questList = document.getElementById('quest-list');
                if (!questList) return;
                
                let html = '';
                
                // 显示当前活跃任务
                this.activeQuests.forEach(questId => {
                    const quest = Config.QUESTS[questId];
                    if (!quest) return;
                    
                    const progress = this.questProgress[questId] || 0;
                    const progressPercent = Math.min((progress / quest.required) * 100, 100);
                    const isComplete = progress >= quest.required;
                    
                    html += `
                        <div class="quest-item ${isComplete ? 'quest-complete' : ''}" onclick="game.claimQuestReward('${questId}')">
                            <div class="quest-name">${quest.name}</div>
                            <div class="quest-desc">${quest.description}</div>
                            <div class="quest-progress">
                                <div class="quest-progress-fill" style="width: ${progressPercent}%"></div>
                            </div>
                            <div class="quest-progress-text">${progress}/${quest.required}</div>
                            ${isComplete ? '<div class="quest-complete-text">可领取奖励</div>' : ''}
                        </div>
                    `;
                });
                
                if (html === '') {
                    html = '<div class="quest-item">暂无活跃任务</div>';
                }
                
                questList.innerHTML = html;
            }
            
            /**
             * 更新任务进度
             * @param {string} type - 任务类型
             * @param {number} amount - 增加数量
             */
            updateQuestProgress(type, amount = 1) {
                this.activeQuests.forEach(questId => {
                    const quest = Config.QUESTS[questId];
                    if (!quest) return;
                    
                    // 检查任务类型是否匹配
                    let shouldUpdate = false;
                    
                    switch(quest.type) {
                        case 'count':
                            if (quest.target === type) {
                                shouldUpdate = true;
                            }
                            break;
                        case 'build':
                            if (quest.target === type && type !== 'gold') {
                                shouldUpdate = true;
                            }
                            break;
                    }
                    
                    // 特殊处理金币任务
                    if (quest.target === 'gold' && type === 'gold') {
                        this.questProgress[questId] = this.gold;
                        shouldUpdate = false; // 不累加，直接设置
                    }
                    
                    if (shouldUpdate) {
                        this.questProgress[questId] = (this.questProgress[questId] || 0) + amount;
                        
                        // 检查任务是否完成
                        if (this.questProgress[questId] >= quest.required) {
                            this.questProgress[questId] = quest.required; // 防止超过
                        }
                    }
                });
                
                // 更新任务显示
                this.updateQuestDisplay();
            }
            
            /**
             * 领取任务奖励
             * @param {string} questId - 任务ID
             */
            claimQuestReward(questId) {
                const quest = Config.QUESTS[questId];
                if (!quest) return;
                
                const progress = this.questProgress[questId] || 0;
                if (progress < quest.required) {
                    this.showNotification('任务尚未完成', 'error');
                    return;
                }
                
                // 发放奖励
                if (quest.reward.gold) {
                    this.gold += quest.reward.gold;
                    this.showNotification(`获得${quest.reward.gold}金币奖励`);
                }
                if (quest.reward.charm) {
                    this.charm += quest.reward.charm;
                    this.showNotification(`获得${quest.reward.charm}魅力值奖励`);
                }
                if (quest.reward.exp) {
                    // 给所有冒险者增加经验
                    this.adventurers.forEach(adventurer => {
                        adventurer.exp += quest.reward.exp;
                        this.checkAdventurerLevelUp(adventurer);
                    });
                    this.showNotification(`所有冒险者获得${quest.reward.exp}经验值`);
                }
                
                // 完成任务
                this.completeQuest(questId);
                
                // 更新资源显示
                this.updateResourceDisplay();
            }
            
            /**
             * 完成任务
             * @param {string} questId - 任务ID
             */
            completeQuest(questId) {
                const quest = Config.QUESTS[questId];
                if (!quest) return;
                
                // 从活跃任务中移除
                const index = this.activeQuests.indexOf(questId);
                if (index > -1) {
                    this.activeQuests.splice(index, 1);
                }
                
                // 添加到已完成任务
                this.completedQuests.push(questId);
                
                // 解锁建筑
                if (quest.unlockBuilding) {
                    this.showNotification(`解锁新建筑：${quest.unlockBuilding}`);
                }
                
                // 激活新任务
                this.activateNewQuests();
                
                this.showAchievement(`任务完成！`, `完成了任务：${quest.name}`);
                this.addLogEntry(`完成了任务：${quest.name}`, 'success');
                this.updateQuestDisplay();
            }
            
            /**
             * 激活新任务
             */
            activateNewQuests() {
                const allQuests = Object.keys(Config.QUESTS);
                
                allQuests.forEach(questId => {
                    // 检查是否已经激活或完成
                    if (this.activeQuests.includes(questId) || this.completedQuests.includes(questId)) {
                        return;
                    }
                    
                    // 根据完成数量决定激活新任务
                    if (this.completedQuests.length >= this.activeQuests.length) {
                        this.activeQuests.push(questId);
                        const quest = Config.QUESTS[questId];
                        this.showNotification(`新任务：${quest.name}`);
                    }
                });
            }
            
            /**
             * 创建新的冒险者
             * 随机生成名字、职业和属性的冒险者
             */
            createAdventurer() {
                if (this.adventurers.length >= Config.MAX_ADVENTURERS + (this.titleEffects.maxAdventurers || 0)) return null;

                const names = ['艾伦', '莉亚', '加尔', '米娅', '雷欧', '艾莎', '卡尔', '露娜', '维克托', '索菲亚', '艾米丽', '凯文', '瑞秋', '大卫', '丽莎'];
                const classes = Object.keys(Config.CLASSES);

                const name = names[Math.floor(Math.random() * names.length)];
                const className = classes[Math.floor(Math.random() * classes.length)];

                const adventurer = {
                    id: Date.now() + Math.random(),
                    name: `${name}`,
                    class: className,
                    level: 1,
                    exp: 0,
                    maxExp: 100,
                    hp: 100,
                    maxHp: 100,
                    mp: 50,
                    maxMp: 50,
                    hunger: 100,
                    maxHunger: 100,
                    attack: 10,
                    defense: 5,
                    speed: 5,
                    critRate: 0.05,
                    critDamage: 1.5,
                    gold: 100, // 增加初始金币，确保能够支付饭店费用
                    powerScore: 0, // 实力评分
                    highestDungeonFloor: 0, // 副本最高通关层数
                    // 使用改进的分散式起始位置，避免聚集在一起
                    ...this.generateScatteredPosition(this.gameAreaWidth, this.gameAreaHeight, 50),
                    target: null,
                    state: 'idle',
                    deathTime: null,
                    equipment: {
                        '武器': null,
                        '头盔': null,
                        '胸甲': null,
                        '护手': null,
                        '护腿': null,
                        '靴子': null,
                        '项链': null,
                        '戒指': null
                    },
                    inventory: [],
                    log: [],
                    lastAction: Date.now(),
                    repairTarget: null,
                    enchantTarget: null,
                    skills: [...Config.CLASSES[className].skills],
                    // 添加技能冷却时间系统
                    skillCooldowns: {},
                    canChangeClass: false,
                    classChangeLevel: 20
                };

                this.adjustAdventurerStatsByClass(adventurer);
                this.generateStarterEquipment(adventurer);
                this.updateEquipmentBonuses(adventurer);
                this.calculateAdventurerPowerScore(adventurer);

                this.adventurers.push(adventurer);
                this.updateAdventurerList();

                this.showNotification(`${adventurer.name}加入了冒险村 (实力评分: ${adventurer.powerScore})`);
                this.addLogEntry(`${adventurer.name} (Lv.1 ${adventurer.class}) 加入了冒险村 (实力评分: ${adventurer.powerScore})`, 'success');

                return adventurer;
            }

            /**
             * 创建副本队伍
             * 选择四名冒险者组成队伍进入副本探险
             * 
             * @param {Array} adventurerIds - 冒险者ID数组
             * @returns {Object} 队伍对象
             */
            createDungeonTeam(adventurerIds) {
                // 检查队伍人数
                if (adventurerIds.length > Config.DUNGEON_CONFIG.MAX_TEAM_SIZE) {
                    this.showNotification(`队伍人数不能超过${Config.DUNGEON_CONFIG.MAX_TEAM_SIZE}人`, 'error');
                    return null;
                }

                // 获取冒险者对象
                const teamMembers = [];
                for (const id of adventurerIds) {
                    const adventurer = this.adventurers.find(a => a.id === id);
                    if (adventurer) {
                        teamMembers.push(adventurer);
                    }
                }

                // 创建队伍对象
                const team = {
                    id: Date.now(),
                    members: teamMembers,
                    currentFloor: 1,
                    highestFloor: 1,
                    startTime: Date.now(),
                    isCompleted: false
                };

                this.dungeonTeams.push(team);
                return team;
            }

            /**
             * 生成副本怪物
             * 根据队伍平均等级和当前层数生成怪物
             * 
             * @param {Object} team - 队伍对象
             * @returns {Object} 怪物对象
             */
            createDungeonMonster(team) {
                // 计算队伍平均等级
                const avgLevel = Math.floor(team.members.reduce((sum, a) => sum + a.level, 0) / team.members.length);
                
                // 计算怪物等级（基于队伍平均等级和当前层数）
                const level = Math.max(1, avgLevel + Math.floor((team.currentFloor - 1) / 10));
                
                // 计算怪物属性增强（每10层增加1%）
                const floorMultiplier = 1 + Math.floor((team.currentFloor - 1) / Config.DUNGEON_CONFIG.FLOOR_INCREMENT) * Config.DUNGEON_CONFIG.STAT_INCREASE_PER_FLOOR;
                
                // 随机选择怪物类型
                const type = Config.MONSTER_TYPES[Math.floor(Math.random() * Config.MONSTER_TYPES.length)];
                const rank = Config.MONSTER_RANKS[Math.floor(Math.random() * Config.MONSTER_RANKS.length)];
                const behavior = Config.MONSTER_BEHAVIORS[Math.floor(Math.random() * Config.MONSTER_BEHAVIORS.length)];
                const attribute = Object.keys(Config.MONSTER_ATTRIBUTES)[Math.floor(Math.random() * Object.keys(Config.MONSTER_ATTRIBUTES).length)];
                
                // 生成怪物对象
                const monster = {
                    id: Date.now() + Math.random(),
                    type: type,
                    rank: rank,
                    level: level,
                    behavior: behavior,
                    attribute: attribute,
                    x: this.gameAreaWidth / 2,
                    y: this.gameAreaHeight / 2,
                    targetX: null,
                    targetY: null,
                    hp: Math.floor(100 * level * floorMultiplier * Config.DUNGEON_CONFIG.MONSTER_STAT_MULTIPLIER),
                    maxHp: Math.floor(100 * level * floorMultiplier * Config.DUNGEON_CONFIG.MONSTER_STAT_MULTIPLIER),
                    attack: Math.floor(10 * level * floorMultiplier * Config.DUNGEON_CONFIG.MONSTER_STAT_MULTIPLIER),
                    defense: Math.floor(5 * level * floorMultiplier * Config.DUNGEON_CONFIG.MONSTER_STAT_MULTIPLIER),
                    speed: Math.floor(3 * level * floorMultiplier * Config.DUNGEON_CONFIG.MONSTER_STAT_MULTIPLIER),
                    // 副本怪物经验为普通怪物的10倍
                    exp: Math.floor(20 * level * 10),
                    gold: Math.floor(10 * level),
                    dropRate: 0.3 + (team.currentFloor * 0.005) // 掉落率随层数增加
                };
                
                return monster;
            }

            /**
             * 生成副本装备
             * 根据当前层数生成增强属性的装备
             * 
             * @param {Object} team - 队伍对象
             * @param {number} level - 装备等级
             * @returns {Object} 装备对象
             */
            createDungeonEquipment(team, level) {
                // 计算装备属性增强（每10层增加1%）
                const floorBoost = 1 + Math.floor((team.currentFloor - 1) / Config.DUNGEON_CONFIG.FLOOR_INCREMENT) * Config.DUNGEON_CONFIG.EQUIPMENT_BOOST_PER_FLOOR;
                
                // 随机选择稀有度（按要求：仅掉落 传说/神话/超神）
                // 设定分布：传说(红色,index5) 50%，神话(粉色,index6) 30%，彩虹(超神,index8) 20%
                // 其它稀有度不在副本基础掉落中出现
                const rarityRoll = Math.random();
                let rarityIndex;
                if (rarityRoll < 0.50) {
                    rarityIndex = 5; // 红色（传说） 50%
                } else if (rarityRoll < 0.80) {
                    rarityIndex = 6; // 粉色（神话） 30%
                } else {
                    rarityIndex = 8; // 彩虹（超神） 20%
                }
                
                // 随机选择装备部位
                const slot = Config.EQUIPMENT_SLOTS[Math.floor(Math.random() * Config.EQUIPMENT_SLOTS.length)];
                
                // 生成装备
                const equipment = this.createEquipment(level, rarityIndex, slot);

                // ===== 优先选择与队伍成员职业匹配的套装（满足用户需求1） =====
                // 如果当前随机生成的装备没有套装，或者希望更偏向职业套装，则尝试根据队伍成员职业选择套装
                try {
                    // 收集队伍中所有职业
                    const teamClasses = Array.from(new Set(team.members.map(m => m.class)));

                    // 在配置中查找与这些职业匹配的套装名称
                    const candidateSets = [];
                    for (const setName in Config.EQUIPMENT_SETS) {
                        const setCfg = Config.EQUIPMENT_SETS[setName];
                        if (setCfg && Array.isArray(setCfg.class)) {
                            // 若套装配置的 class 与队伍中任意职业匹配，则加入候选
                            for (const cls of teamClasses) {
                                if (setCfg.class.includes(cls)) {
                                    candidateSets.push(setName);
                                    break;
                                }
                            }
                        }
                    }

                    // 若找到候选套装，则以一定概率使用职业套装（提高世界副本掉落的职业相关性）
                    if (candidateSets.length > 0 && Math.random() < 0.9) {
                        const chosenSet = candidateSets[Math.floor(Math.random() * candidateSets.length)];
                        equipment.set = '套装：' + chosenSet;
                        // 套装装备略微提升属性（蓝色及以上稀有度已有处理，这里保持兼容性）
                        if (rarityIndex >= 3) {
                            equipment.attack = Math.floor(equipment.attack * 1.1);
                            equipment.defense = Math.floor(equipment.defense * 1.1);
                            equipment.hp = Math.floor(equipment.hp * 1.1);
                        }
                    }
                } catch (e) {
                    // 如果匹配逻辑出错，不影响掉落流程，记录 debug 信息
                    this.debugLog('createDungeonEquipment: 套装匹配异常', e);
                }

                // 应用副本属性增强（每10层增加1%）
                equipment.attack = Math.floor(equipment.attack * floorBoost);
                equipment.defense = Math.floor(equipment.defense * floorBoost);
                equipment.hp = Math.floor(equipment.hp * floorBoost);
                equipment.mp = Math.floor(equipment.mp * floorBoost);
                equipment.speed = Math.floor(equipment.speed * floorBoost);

                // 添加世界装标记与名称前缀（满足用户需求6）
                equipment.isWorldDrop = true;
                equipment.name = `[世界]${equipment.name}`;

                // 增加装备价值，副本装备价值更高
                equipment.value = Math.floor(equipment.value * floorBoost * 1.5);

                return equipment;
            }

            /**
             * 进入下一层副本
             * 
             * @param {Object} team - 队伍对象
             */
            advanceDungeonFloor(team) {
                team.currentFloor++;
                if (team.currentFloor > team.highestFloor) {
                    team.highestFloor = team.currentFloor;
                }
                
                // 更新队伍成员的最高通关层数
                for (const member of team.members) {
                    if (team.highestFloor > (member.highestDungeonFloor || 0)) {
                        member.highestDungeonFloor = team.highestFloor;
                        this.addLogEntry(`${member.name} 副本最高通关层数更新为 ${team.highestFloor}`, 'success');
                        // 同步记录到全局副本记录对象，便于列表展示和快速查询
                        try {
                            this.dungeonRecords[member.id] = Math.max(this.dungeonRecords[member.id] || 0, member.highestDungeonFloor || 0);
                        } catch (e) {
                            this.debugLog('advanceDungeonFloor -> 更新 dungeonRecords 异常', e);
                        }
                    }
                }
                
                this.showNotification(`进入第${team.currentFloor}层`, 'success');

                // 每进入新一层时，尝试触发一次副本掉落（让队伍有长期掉落机会）
                // 这样可以在没有显式怪物死亡钩子的情况下，保证副本也能产出世界装和奖励
                this.processDungeonLoot(team, null);
            }

            /**
             * 完成副本
             * 
             * @param {Object} team - 队伍对象
             */
            completeDungeon(team) {
                team.isCompleted = true;
                this.dungeonsCompleted++;
                
                // 更新任务进度
                this.updateQuestProgress('dungeon_completed', 1);
                
                // 给队伍成员奖励
                for (const member of team.members) {
                    member.gold += team.highestFloor * 100; // 每层100金币奖励
                    this.showNotification(`${member.name} 获得 ${team.highestFloor * 100} 金币奖励`, 'success');
                    // 完成副本后，同步更新全局副本记录
                    try {
                        this.dungeonRecords[member.id] = Math.max(this.dungeonRecords[member.id] || 0, member.highestDungeonFloor || 0);
                    } catch (e) {
                        this.debugLog('completeDungeon -> 更新 dungeonRecords 异常', e);
                    }
                }
                
                this.showNotification(`副本完成！最高到达第${team.highestFloor}层`, 'success');
                this.addLogEntry(`队伍完成副本，最高到达第${team.highestFloor}层`, 'success');
            }

            /**
             * 启动副本运行器 - 简单的异步循环模拟每层战斗
             * @param {Object} team
             */
            startDungeonRun(team) {
                if (!team || team.isCompleted) return;
                // 标记队伍为正在运行
                team.isRunning = true;
                team._dungeonRunId = Date.now() + Math.random();

                // 标记队伍成员为“在副本中”，以便暂停世界AI行为（例如移动、吃饭等）
                try {
                    for (const member of team.members) {
                        if (!member) continue;
                        // 保存原始状态，便于恢复
                        member._prevState = member.state;
                        member._inDungeon = true;
                        member.state = 'inDungeon';
                    }
                } catch (e) {
                    this.debugLog('startDungeonRun -> 标记成员状态异常', e);
                }

                // 异步开始第一步（不阻塞主线程）
                setTimeout(() => this._runDungeonStep(team), 200);
            }

            /**
             * 结束副本运行：恢复成员状态并做必要清理
             * @param {Object} team
             */
            endDungeonRun(team) {
                if (!team) return;
                try {
                    for (const member of team.members) {
                        if (!member) continue;
                        // 只有在我们标记过的成员才做恢复
                        if (member._inDungeon) {
                            member._inDungeon = false;
                            // 若成员处于死亡状态，保持死亡；否则恢复到闲置
                            if (member.state !== 'dead') {
                                member.state = member._prevState || 'idle';
                                // 清理临时字段
                                delete member._prevState;
                            }
                        }
                    }
                } catch (e) {
                    this.debugLog('endDungeonRun 异常', e);
                }
            }

            /**
             * 副本单步运行：生成怪物、模拟战斗结果、处理掉落并推进层数
             * 这是一个非常保守的模拟：按队伍总实力对比怪物，胜利则 advance，失败则按惩罚处理
             */
            _runDungeonStep(team) {
                try {
                    if (!team || team.isCompleted || !team.isRunning) return;

                    // 确保队伍还有存活成员
                    const aliveMembers = team.members.filter(m => m && m.state !== 'dead');
                    if (aliveMembers.length === 0) {
                        this.addLogEntry('队伍所有成员已死亡，副本失败', 'error');
                        team.isRunning = false;
                        // 恢复成员的世界状态
                        try { this.endDungeonRun(team); } catch (e) { this.debugLog('_runDungeonStep -> endDungeonRun 异常', e); }
                        return;
                    }

                    // 生成副本怪物
                    const monster = this.createDungeonMonster(team);

                    // 在正式判定胜负之前，模拟一轮“战斗回合”行为：职业分工/技能/治疗/自动使用药水等
                    try {
                        // 1) 自动使用药水（当成员 HP 低于阈值时）
                        aliveMembers.forEach(m => {
                            if (!m || m.state === 'dead') return;
                            // 如果背包中有药水（标记为 item.type === 'potion' 或 name 包含 '药水'），则在低血量时使用
                            if (m.hp / m.maxHp < 0.35) {
                                const potionIndex = m.inventory.findIndex(it => it && (it.type === 'potion' || (it.name && it.name.includes('药水'))));
                                if (potionIndex > -1) {
                                    const potion = m.inventory.splice(potionIndex, 1)[0];
                                    const healAmount = Math.floor(m.maxHp * (potion.effectHealPercent || 0.25));
                                    m.hp = Math.min(m.maxHp, m.hp + healAmount);
                                    m.log.push(`${new Date().toLocaleTimeString()} 使用药水恢复 ${healAmount} 点生命`);
                                    this.addLogEntry(`${m.name} 在副本中使用了药水，恢复 ${healAmount} HP`, 'info');
                                }
                            }
                        });

                        // 2) 职业分工：牧师优先治疗队友，战士吸收/嘲讽（降低所受伤害），法师造成额外法术伤害
                        // 简化实现：牧师会选择血量最少且非死亡的队友施放一次治疗术（有概率成功），法师对怪物造成额外伤害加成，战士提供减伤加成
                        let teamHealAmount = 0;
                        let teamMagicBonus = 0;
                        let teamPhysicalShield = 0;

                        aliveMembers.forEach(m => {
                            if (m.class === '牧师') {
                                // 牧师施放治疗术（如果存在技能且冷却允许）
                                const target = aliveMembers.filter(x => x.state !== 'dead').sort((a,b) => (a.hp/a.maxHp) - (b.hp/b.maxHp))[0];
                                if (target && (target.hp / target.maxHp) < 0.9) {
                                    const heal = Math.floor(target.maxHp * 0.18); // 基本治疗量
                                    target.hp = Math.min(target.maxHp, target.hp + heal);
                                    this.addLogEntry(`${m.name} 使用治疗术，为 ${target.name} 恢复 ${heal} HP`, 'info');
                                }
                            } else if (m.class === '法师') {
                                // 法师增加团队法术伤害加成
                                teamMagicBonus += Math.floor((m.powerScore || this.calculateAdventurerPowerScore(m)) * 0.05);
                            } else if (m.class === '战士') {
                                // 战士提供物理减伤（等价于降低怪物攻击对队伍造成的伤害）
                                teamPhysicalShield += Math.floor((m.powerScore || this.calculateAdventurerPowerScore(m)) * 0.03);
                            }
                        });

                        // 3) 将职业加成反映到队伍实力计算中（暂为直接数值调整）
                        // 计算队伍总实力（包含装备/属性评分），随后在判定中将 monsterPower 减去 teamMagicBonus/增加 teamPhysicalShield 的效果体现
                    } catch (e) {
                        this.debugLog('_runDungeonStep -> 职业分工/药水逻辑 异常', e);
                    }

                    // 简单战斗判定：计算队伍总实力 vs 怪物强度（包含职业加成）
                    const teamPower = aliveMembers.reduce((s, m) => s + (m.powerScore || this.calculateAdventurerPowerScore(m)), 0);
                    // 把法术加成与物理减伤简单映射为对怪物威力的调整
                    const magicBonus = Math.floor(aliveMembers.reduce((s, m) => s + ((m.class === '法师') ? Math.floor((m.powerScore || this.calculateAdventurerPowerScore(m)) * 0.05) : 0), 0));
                    const physicalShield = Math.floor(aliveMembers.reduce((s, m) => s + ((m.class === '战士') ? Math.floor((m.powerScore || this.calculateAdventurerPowerScore(m)) * 0.03) : 0), 0));
                    const monsterPower = Math.max(1, monster.hp + monster.attack * 10 + monster.defense * 5 - magicBonus - physicalShield);

                    // 判定胜负（加入随机因素）
                    const winChance = teamPower / (teamPower + monsterPower);
                    const didWin = Math.random() < Math.min(0.95, Math.max(0.05, winChance));

                    if (didWin) {
                            this.monstersDefeated = (this.monstersDefeated || 0) + 1;
                            this.addLogEntry(`第${team.currentFloor}层：队伍击败了 ${monster.rank}${monster.type}`, 'success');

                            // 计算并分配经验：副本规则为“队伍平方经验”
                            try {
                                const teamSize = aliveMembers.length;
                                const totalExp = Math.max(0, monster.exp) * Math.max(1, teamSize * teamSize); // monster.exp 已经是副本经验基准（10倍）
                                const perMemberExp = Math.floor(totalExp / teamSize);
                                aliveMembers.forEach(m => {
                                    m.exp = (m.exp || 0) + perMemberExp;
                                    this.checkAdventurerLevelUp(m);
                                    this.addLogEntry(`${m.name} 获得 ${perMemberExp} 经验（副本奖励）`, 'info');
                                });
                            } catch (e) {
                                this.debugLog('经验分配异常', e);
                            }

                            // 触发掉落（按副本掉落规则：生成更多装备，这里实现为每次掉落4件并随机分配）
                            this.processDungeonLoot(team, monster);

                            // 处理战斗后状态：少量HP损失给每个参战成员
                            aliveMembers.forEach(m => {
                                const dmg = Math.max(1, Math.floor(monster.attack * 0.5 * (1 + Math.random() * 0.3)));
                                m.hp = Math.max(0, m.hp - dmg);
                                if (m.hp <= 0) {
                                    m.state = 'dead';
                                    m.deathTime = Date.now();
                                    this.addLogEntry(`${m.name} 在副本中阵亡`, 'error');
                                }
                            });

                        // 推进到下一层
                        this.advanceDungeonFloor(team);

                        // 如果队伍未完成且仍有生者，继续下一层
                        if (!team.isCompleted) {
                            setTimeout(() => this._runDungeonStep(team), 300 + Math.random() * 700);
                        }
                    } else {
                        // 失败处理：队伍受到较大伤害，可能阵亡或撤退
                        this.addLogEntry(`第${team.currentFloor}层：队伍被 ${monster.rank}${monster.type} 击退`, 'warning');
                        aliveMembers.forEach(m => {
                            const dmg = Math.max(1, Math.floor(monster.attack * (0.6 + Math.random() * 0.8)));
                            m.hp = Math.max(0, m.hp - dmg);
                            if (m.hp <= 0) {
                                m.state = 'dead';
                                m.deathTime = Date.now();
                                this.addLogEntry(`${m.name} 在副本中阵亡`, 'error');
                            } else {
                                // 撤退后的冷却和状态
                                m.state = 'idle';
                                m.combatCooldown = Date.now() + 15000; // 15秒冷却
                            }
                        });

                        // 停止当前副本运行
                        team.isRunning = false;
                        // 恢复成员的世界状态
                        try { this.endDungeonRun(team); } catch (e) { this.debugLog('_runDungeonStep -> endDungeonRun 异常', e); }
                        this.addLogEntry('队伍被迫撤退，副本结束', 'info');
                    }

                    // 更新UI
                    this.updateDungeonTab();
                } catch (e) {
                    this.debugLog('_runDungeonStep 异常', e);
                }
            }

            /**
             * 处理副本掉落（生成装备并分配给队伍成员）
             * - 根据怪物/层数概率生成装备
             * - 将掉落的世界装放入最合适的成员背包并尝试自动穿戴
             * @param {Object} team - 队伍对象
             * @param {Object} monster - 被击杀的怪物对象（可选，用于读取 dropRate）
             */
            processDungeonLoot(team, monster = null) {
                try {
                    // 简单掉落判定：如果传入 monster，则使用其 dropRate，否则按默认概率
                    const dropChance = monster ? (monster.dropRate || 0.1) : 0.2;
                    if (Math.random() > dropChance) return; // 无掉落

                    // 生成装备等级以队伍平均等级为基础
                    const avgLevel = Math.max(1, Math.floor(team.members.reduce((s, m) => s + m.level, 0) / team.members.length));
                    // 随机选择一个队伍成员作为首选接收者（便于自动穿戴）
                    const receiver = team.members[Math.floor(Math.random() * team.members.length)];

                    // 副本掉落策略：生成多件世界装（普通的4倍掉落），并随机平均分配给队伍成员
                    const dropCount = 4; // 副本掉落数量放大为4
                    const generated = [];
                    for (let i = 0; i < dropCount; i++) {
                        const equipment = this.createDungeonEquipment(team, avgLevel);
                        generated.push(equipment);
                        this.equipmentFound = (this.equipmentFound || 0) + 1;
                    }

                    // 平均随机分配：把生成的装备随机分配到队伍成员的背包
                    for (const eq of generated) {
                        const recv = team.members[Math.floor(Math.random() * team.members.length)];
                        if (recv) {
                            recv.inventory.push(eq);
                            this.addLogEntry(`${recv.name} 在副本中获得装备：${eq.name}`, 'success');
                            // 尝试自动穿戴（可能为职业套装并触发硬优先逻辑）
                            try {
                                this.tryAutoEquip(recv, eq);
                            } catch (e) {
                                this.debugLog('processDungeonLoot -> tryAutoEquip 异常', e);
                            }
                        }
                    }
                } catch (e) {
                    this.debugLog('processDungeonLoot 异常', e);
                }
            }

            /**
             * 尝试自动穿戴新获得装备到冒险者身上
             * - 仅在装备插槽为空或新装备综合价值更高时替换
             * - 优先穿戴与冒险者职业套装匹配的装备
             * @param {Object} adventurer
             * @param {Object} equipment
             */
            tryAutoEquip(adventurer, equipment) {
                try {
                    if (!adventurer || !equipment) return;
                    const slot = equipment.slot;
                    const current = adventurer.equipment[slot];

                    // 计算装备评分（使用已有的 calculateEquipmentValue）
                    const newVal = this.calculateEquipmentValue(equipment);
                    const curVal = current ? this.calculateEquipmentValue(current) : -Infinity;

                    // ===== 强化逻辑：职业套装硬优先 =====
                    // 规则：若装备属于该冒险者职业套装，则即使评分略差（例如 >= 90%）也会优先替换当前装备
                    let isCareerSet = false;
                    if (equipment.set) {
                        for (const setName in Config.EQUIPMENT_SETS) {
                            if (equipment.set.includes(setName)) {
                                const setCfg = Config.EQUIPMENT_SETS[setName];
                                if (setCfg && Array.isArray(setCfg.class) && setCfg.class.includes(adventurer.class)) {
                                    isCareerSet = true;
                                    break;
                                }
                            }
                        }
                    }

                    // 自动穿戴条件：
                    // 1) 当前为空 -> 装备
                    // 2) 新装备评分显著更高 -> 装备
                    // 3) 新装备为职业套装且新Val >= curVal * 0.9 -> 强制替换（硬优先）
                    if (!current || newVal > curVal || (isCareerSet && newVal >= curVal * 0.9)) {
                        this.equipItem(equipment, adventurer);
                        this.addLogEntry(`${adventurer.name} 自动装备了 ${equipment.name}`, 'info');
                    }
                } catch (e) {
                    this.debugLog('tryAutoEquip 异常', e);
                }
            }

            adjustAdventurerStatsByClass(adventurer) {
                const classStats = Config.CLASSES[adventurer.class];
                const growth = classStats.growth;

                // 基础属性调整
                adventurer.attack += classStats.attack;
                adventurer.defense += classStats.defense;
                adventurer.maxHp += classStats.hp;
                adventurer.hp = adventurer.maxHp;
                adventurer.maxMp += classStats.mp;
                adventurer.mp = adventurer.maxMp;
                adventurer.speed += classStats.speed;

                // 设置成长属性
                adventurer.growth = growth;
            }

            generateStarterEquipment(adventurer) {
                Config.EQUIPMENT_SLOTS.forEach(slot => {
                    const equipment = this.createEquipment(1, 0, slot, true); // 白色品质新手装备
                    adventurer.equipment[slot] = equipment;
                });
            }

            /**
             * 创建装备 - 装备生成系统的核心方法
             * 根据指定的等级、稀有度和部位生成随机装备
             * 装备具有复杂的属性系统，包括基础属性、词缀、特殊效果等
             * 
             * 装备生成流程：
             * 1. 初始化装备基础信息（ID、名称、稀有度等）
             * 2. 生成词缀系统
             * 3. 根据部位和稀有度计算基础属性
             * 4. 应用词缀属性加成
             * 5. 添加特殊效果（根据稀有度）
             * 6. 添加套装属性（高级装备）
             * 7. 添加神话属性（顶级装备）
             * 8. 添加传说属性（传说装备）
             * 9. 计算装备价值
             * 
             * @param {number} level - 装备等级
             * @param {number} rarityIndex - 稀有度索引（0-8对应白到彩虹）
             * @param {string} slot - 装备部位
             * @param {boolean} isStarter - 是否为新手装备
             * @returns {Object} 生成的装备对象
             */
            /**
             * 创建装备方法
             * 根据指定的等级、稀有度和部位生成新的装备
             * @param {number} level - 装备等级
             * @param {number} rarityIndex - 稀有度索引（0-8对应白到彩虹）
             * @param {string} slot - 装备部位
             * @param {boolean} isStarter - 是否为新手装备
             * @returns {Object} 生成的装备对象
             */
            createEquipment(level, rarityIndex, slot, isStarter = false) {
                // 获取稀有度名称（白色、绿色、蓝色等）
                const rarity = Config.EQUIPMENT_RARITIES[rarityIndex];
                // 生成词缀系统（根据稀有度生成不同数量的词缀）
                const affixes = this.generateEquipmentAffixes(rarityIndex);
                // 随机选择武器类型（仅对武器有效）
                const weaponType = Config.WEAPON_TYPES[Math.floor(Math.random() * Config.WEAPON_TYPES.length)];

                // 初始化装备基础信息
                const equipment = {
                    id: Date.now() + Math.random(), // 唯一ID
                    name: this.generateEquipmentName(rarity, slot, affixes, weaponType), // 装备名称
                    slot, // 装备部位
                    rarity, // 稀有度
                    level, // 装备等级
                    weaponType: slot === '武器' ? weaponType : null, // 武器类型
                    attack: 0, // 攻击力
                    defense: 0, // 防御力
                    hp: 0, // 生命值
                    mp: 0, // 魔法值
                    speed: 0, // 速度
                    critRate: 0, // 暴击率
                    critDamage: 0, // 暴击伤害
                    durability: 100, // 耐久度
                    maxDurability: 100, // 最大耐久度
                    value: level * (rarityIndex + 1) * 15, // 基础价值
                    affixes: affixes, // 词缀列表
                    special: null, // 特殊效果
                    set: null, // 套装属性
                    bonus: null, // 神话属性
                    enchantLevel: 0, // 强化等级
                    gemSlots: this.generateGemSlots(rarityIndex), // 宝石槽
                    socketedGems: [], // 已镶嵌宝石
                    quality: 100, // 品质 (0-100)
                    prefix: null, // 前缀
                    suffix: null, // 后缀
                    legendary: null, // 传说属性
                    isEnchanted: false // 附魔状态标记
                };

                // 根据稀有度和等级生成基础属性
                // 基础属性值 = 等级 × 稀有度系数 × 品质系数
                const baseStat = level * (rarityIndex + 1) * (equipment.quality / 100);
                // 属性波动范围：80%-120%
                const statVariation = 0.8 + Math.random() * 0.4;

                // 根据装备部位计算基础属性
                if (slot === '武器') {
                    // 武器主要提供攻击力
                    equipment.attack = Math.floor(baseStat * statVariation * 1.2);
                    // 法系武器额外提供魔法值
                    if (weaponType === '法杖' || weaponType === '法珠' || weaponType === '魔導器') {
                        equipment.mp += Math.floor(baseStat * 0.5);
                    }
                } else if (slot === '项链' || slot === '戒指' || slot === '腰带' || slot === '护符') {
                    // 饰品类装备提供综合属性
                    equipment.attack = Math.floor(baseStat * statVariation * 0.6);
                    equipment.defense = Math.floor(baseStat * statVariation * 0.4);
                    equipment.hp = Math.floor(baseStat * statVariation * 3);
                } else {
                    // 防具类装备主要提供防御力和生命值
                    equipment.defense = Math.floor(baseStat * statVariation);
                    equipment.hp = Math.floor(baseStat * statVariation * 2);
                }

                // 添加词缀属性 - 根据词缀类型增加相应属性
                this.applyAffixes(equipment, affixes);
                
                // 高级装备有几率带特殊效果（橙色及以上稀有度）
                if (rarityIndex >= 4 && Math.random() < 0.4) {
                    equipment.special = this.generateSpecialEffect(rarityIndex, slot);
                }

                // 传说及以上装备可能有套装属性（蓝色及以上稀有度）
                if (rarityIndex >= 3 && Math.random() < 0.25) {
                    const sets = Object.keys(Config.EQUIPMENT_SETS);
                    const setName = sets[Math.floor(Math.random() * sets.length)];
                    equipment.set = '套装：' + setName;
                    
                    // 套装装备有额外属性加成
                    if (rarityIndex >= 4) { // 橙色及以上稀有度
                        equipment.attack = Math.floor(equipment.attack * 1.1);
                        equipment.defense = Math.floor(equipment.defense * 1.1);
                        equipment.hp = Math.floor(equipment.hp * 1.1);
                    }
                }

                // 粉色神话装备额外属性（神话装备专属）
                if (rarityIndex >= 6) {
                    equipment.bonus = '神话属性：全属性+' + Math.floor(baseStat * 0.3);
                }
                
                // 金色和彩虹装备的特殊属性（传说装备专属）
                if (rarityIndex >= 7) {
                    equipment.legendary = this.generateLegendaryEffect(slot, weaponType); // 传说属性
                    equipment.enchantLevel = Math.floor(Math.random() * 3) + 1; // 随机强化等级
                }
                
                // 计算最终价值 - 综合考虑所有属性和特殊效果
                equipment.value = this.calculateEquipmentValue(equipment);
                
                // 套装装备价值更高
                if (equipment.set) {
                    equipment.value = Math.floor(equipment.value * 1.3);
                }

                return equipment;
            }

            /**
             * 生成装备名称 - 装备命名系统
             * 根据装备的稀有度、部位、词缀和武器类型生成合适的名称
             * 名称结构：[词缀前缀][武器类型/装备部位][稀有度后缀]
             * 
             * 命名规则：
             * 1. 优先使用第一个词缀作为前缀
             * 2. 武器显示具体类型，其他装备显示部位
             * 3. 非白色装备添加稀有度前缀
             * 
             * @param {string} rarity - 装备稀有度
             * @param {string} slot - 装备部位
             * @param {Array} affixes - 词缀列表
             * @param {string} weaponType - 武器类型（仅对武器有效）
             * @returns {string} 生成的装备名称
             */
            generateEquipmentName(rarity, slot, affixes, weaponType) {
                let name = '';
                
                // 前缀词缀 - 使用第一个词缀作为装备名称前缀
                if (affixes.length > 0) {
                    name = affixes[0];
                }
                
                // 武器类型 - 武器显示具体类型，其他装备显示部位
                if (slot === '武器' && weaponType) {
                    name += weaponType; // 武器类型（如剑、法杖等）
                } else {
                    name += slot; // 装备部位（如头盔、胸甲等）
                }
                
                // 稀有度后缀 - 非白色装备添加稀有度前缀以示区分
                if (rarity !== '白色') {
                    name = rarity + name; // 稀有度+名称
                }
                
                return name;
            }
            
            /**
             * 生成宝石槽数量 - 装备宝石系统
             * 根据装备稀有度确定可镶嵌的宝石槽数量
             * 稀有度越高，宝石槽越多，提升装备潜力
             * 
             * 宝石槽分配规则：
             * - 白色、绿色：0个宝石槽
             * - 蓝色、紫色：1个宝石槽
             * - 橙色、红色：2个宝石槽
             * - 粉色及以上：3个宝石槽
             * 
             * @param {number} rarityIndex - 装备稀有度索引
             * @returns {number} 宝石槽数量
             */
            generateGemSlots(rarityIndex) {
                if (rarityIndex < 2) return 0; // 白色和绿色没有宝石槽
                if (rarityIndex < 4) return 1; // 蓝色和紫色有1个
                if (rarityIndex < 6) return 2; // 橙色和红色有2个
                return 3; // 粉色及以上有3个
            }
            
            /**
             * 生成特殊效果 - 装备特殊能力系统
             * 根据装备部位和稀有度生成相应的特殊效果
             * 不同部位具有不同类型的特殊效果，增强装备独特性
             * 
             * 特殊效果分类：
             * - 武器：攻击类效果（元素攻击、吸血等）
             * - 防具：防御类效果（抵抗、恢复等）
             * - 饰品：辅助类效果（加成、移动等）
             * 
             * @param {number} rarityIndex - 装备稀有度索引
             * @param {string} slot - 装备部位
             * @returns {string} 特殊效果描述
             */
            generateSpecialEffect(rarityIndex, slot) {
                // 各部位对应的特殊效果列表
                const effects = {
                    '武器': ['火焰攻击', '冰霜攻击', '雷电攻击', '毒素攻击', '吸血攻击', '暴击强化', '一击必杀'],
                    '头盔': ['魔法抵抗', '精神保护', '智力提升', '危险感知', '夜视能力'],
                    '胸甲': ['反射伤害', '损伤减免', '生命恢复', '能量屏障', '神圣光环'],
                    '护手': ['攻速提升', '格挡概率', '技能冷却', '精准攻击', '双击效果'],
                    '护腿': ['移动速度', '闪避概率', '跳跃能力', '冲刺攻击', '踢击反击'],
                    '靴子': ['无声行走', '水上行走', '空中漂浮', '闪现技能', '踏击震荡'],
                    '项链': ['魔法恢复', '经验加成', '神圣保护', '魔法反射', '生命链接'],
                    '戒指': ['暴击伤害', '魔法穿透', '时间停止', '瞬间移动', '分身效果'],
                    '腰带': ['负重增加', '药品效果', '财富吸引', '快速恢复', '背包空间'],
                    '护符': ['诅咒抵抗', '不死保护', '元素免疫', '危险预警', '幸运加成']
                };
                
                // 获取对应部位的特殊效果列表，如果没有则使用默认效果
                const slotEffects = effects[slot] || ['神秘效果'];
                // 随机选择一个特殊效果
                return '技能：' + slotEffects[Math.floor(Math.random() * slotEffects.length)];
            }
            
            /**
             * 生成传说效果 - 装备传说属性系统
             * 为传说级装备生成强大的特殊效果
             * 传说效果具有改变游戏机制的潜力，是顶级装备的标志
             * 
             * 传说效果特点：
             * 1. 强大的被动能力
             * 2. 改变战斗机制的效果
             * 3. 独特的游戏体验
             * 4. 极高的稀有价值
             * 
             * @param {string} slot - 装备部位
             * @param {string} weaponType - 武器类型（仅对武器有效）
             * @returns {string} 传说效果描述
             */
            generateLegendaryEffect(slot, weaponType) {
                // 传说效果列表 - 每个都有独特且强大的能力
                const legendaryEffects = {
                    '龙血契约': '攻击时有几率获得龙之力，提升攻速50%',
                    '不死之身': '死亡时有几率立即复活并获得无敌状态',
                    '时空掌控': '攻击时有几率停止时间，获得额外攻击机会',
                    '元素之主': '随机获得不同元素属性，每次攻击都有特殊效果',
                    '天命之子': '所有受到的伤害减半，攻击力随生命值提升',
                    '夜神传承': '在黑夜或阴影中获得全属性大幅提升',
                    '圣光守护': '为附近的所有友军提供保护光环，提升防御力',
                    '血腥诅咒': '每次攻击都会吸取生命值，并有几率发动诅咒攻击'
                };
                
                // 获取所有传说效果的键名
                const effects = Object.keys(legendaryEffects);
                // 随机选择一个传说效果
                const effect = effects[Math.floor(Math.random() * effects.length)];
                // 返回效果名称和详细描述
                return effect + '：' + legendaryEffects[effect];
            }
            
            /**
             * 计算装备价值 - 装备经济系统
             * 根据装备的所有属性和特殊效果计算其市场价值
             * 价值计算考虑了基础属性、稀有度、特殊效果等多个维度
             * 
             * 价值计算公式：
             * 基础价值 = 等级 × 15
             * 稀有度加成 = 基础价值 × (稀有度索引+1) × 2
             * 属性价值 = 各属性值 × 对应系数
             * 特殊效果加成 = 价值倍数
             * 强化加成 = 价值 × (1 + 强化等级 × 0.3)
             * 品质系数 = 价值 × (品质/100)
             * 
             * @param {Object} equipment - 装备对象
             * @returns {number} 装备价值（整数）
             */
            /**
             * 计算装备价值 - 装备经济系统
             * 综合评估装备的各项属性和特殊效果计算出售价值
             * 用于装备出售、交易和经济平衡
             * 支持复杂的装备价值计算模型
             * 
             * 价值计算流程：
             * 1. 基础价值 = 装备等级 × 15
             * 2. 应用稀有度价值倍数
             * 3. 累加各属性价值
             * 4. 应用特殊效果价值倍数
             * 5. 应用强化等级价值加成
             * 6. 应用品质价值系数
             * 7. 返回向下取整的整数价值
             * 
             * 属性价值系数：
             * - 攻击力：×10系数
             * - 防御力：×8系数
             * - 生命值：×2系数
             * - 魔法值：×3系数
             * - 速度：×15系数
             * - 暴击率：×1000系数
             * - 暴击伤害：×500系数
             * 
             * 特殊效果倍数：
             * - 特殊效果：1.5倍
             * - 套装效果：1.8倍
             * - 传说效果：3倍
             * - 神话属性：2倍
             * 
             * 价值加成：
             * - 稀有度：线性增长倍数
             * - 强化等级：线性加成(1+等级×0.3)
             * - 品质：百分比系数(品质/100)
             * - 多重效果可叠加生效
             * 
             * 经济平衡：
             * - 高属性装备价值合理
             * - 特殊效果提供显著加成
             * - 强化投入有经济回报
             * - 避免价值过高破坏平衡
             * 
             * @param {Object} equipment - 装备对象
             * @returns {number} 装备价值(金币)
             */
            /**
             * 计算装备价值 - 装备经济系统
             * 根据装备的所有属性和特殊效果计算其市场价值
             * 价值计算考虑了基础属性、稀有度、特殊效果等多个维度
             * 用于装备出售、交易和经济平衡
             * 
             * 价值计算公式：
             * 基础价值 = 等级 × 15
             * 稀有度加成 = 基础价值 × (稀有度索引+1) × 2
             * 属性价值 = 各属性值 × 对应系数
             * 特殊效果加成 = 价值倍数
             * 强化加成 = 价值 × (1 + 强化等级 × 0.3)
             * 品质系数 = 价值 × (品质/100)
             * 最终价值 = 向下取整的整数价值
             * 
             * 属性价值系数：
             * - 攻击力：×10系数
             * - 防御力：×8系数
             * - 生命值：×2系数
             * - 魔法值：×3系数
             * - 速度：×15系数
             * - 暴击率：×1000系数
             * - 暴击伤害：×500系数
             * 
             * 特殊效果倍数：
             * - 特殊效果：1.5倍
             * - 套装效果：1.8倍
             * - 传说效果：3倍
             * - 神话属性：2倍
             * 
             * 价值加成机制：
             * - 稀有度：线性增长倍数
             * - 强化等级：线性加成(1+等级×0.3)
             * - 品质：百分比系数(品质/100)
             * - 多重效果可叠加生效
             * 
             * 经济平衡设计：
             * - 高属性装备价值合理
             * - 特殊效果提供显著加成
             * - 强化投入有经济回报
             * - 避免价值过高破坏平衡
             * 
             * @param {Object} equipment - 装备对象
             * @returns {number} 装备价值（整数）
             */
            calculateEquipmentValue(equipment) {
                // 为避免未定义属性导致 NaN，所有数值字段都使用 Number(...) 并设置合理默认值
                const level = Number(equipment && equipment.level) || 1;
                let value = level * 15; // 基础价值 = 等级 × 15

                // 稀有度价值倍数 - 稀有度越高价值倍数越大
                let rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(equipment && equipment.rarity);
                if (isNaN(rarityIndex) || rarityIndex < 0) rarityIndex = 0;
                value *= (rarityIndex + 1) * 2;

                // 属性价值 - 各属性按不同系数转换为价值（使用默认0）
                const attack = Number(equipment && equipment.attack) || 0;
                const defense = Number(equipment && equipment.defense) || 0;
                const hp = Number(equipment && equipment.hp) || 0;
                const mp = Number(equipment && equipment.mp) || 0;
                const speed = Number(equipment && equipment.speed) || 0;
                const critRate = Number(equipment && equipment.critRate) || 0;
                const critDamage = Number(equipment && equipment.critDamage) || 0;

                value += attack * 10;      // 攻击力系数
                value += defense * 8;      // 防御力系数
                value += hp * 2;           // 生命值系数
                value += mp * 3;           // 魔法值系数
                value += speed * 15;       // 速度系数
                value += critRate * 1000;  // 暴击率系数
                value += critDamage * 500; // 暴击伤害系数
                
                // 特殊效果价值倍数 - 不同特殊效果提供不同价值加成
                if (equipment && equipment.special) value *= 1.5;     // 特殊效果加成
                if (equipment && equipment.set) value *= 1.8;         // 套装效果加成
                if (equipment && equipment.legendary) value *= 3;     // 传说效果加成
                if (equipment && equipment.bonus) value *= 2;         // 神话属性加成
                
                // 强化等级价值 - 强化等级提供线性价值加成
                const enchantLevel = Number(equipment && equipment.enchantLevel) || 0;
                value *= (1 + enchantLevel * 0.3);

                // 品质价值系数 - 品质越高价值越高，默认质量为100（即不改变）
                const quality = Number(equipment && equipment.quality) || 100;
                value *= (quality / 100);
                
                // 返回整数价值
                return Math.floor(value);
            }

            /**
             * 返回稀有度的展示名称（带简短说明），例如 '彩虹（超神）'
             * 不修改 Config.EQUIPMENT_RARITIES 本身，仅用于 UI/调试显示
             * @param {number} index
             * @returns {string}
             */
            getRarityLabel(index) {
                const idx = Number.isFinite(Number(index)) ? Number(index) : 0;
                const name = Config.EQUIPMENT_RARITIES[idx] || '未知';
                const map = {
                    '白色': '普通',
                    '绿色': '高级',
                    '蓝色': '精品',
                    '紫色': '极品',
                    '橙色': '史诗',
                    '红色': '传说',
                    '粉色': '神话',
                    '金色': '稀有',
                    '彩虹': '超神'
                };
                const desc = map[name] || '';
                return desc ? `${name}（${desc}）` : name;
            }

            /**
             * 调试函数：比较副本（世界）掉落装备与普通生成装备的属性/价值差异
             * 在浏览器控制台运行：game.debugCompareDungeonVsNormal(level, floor, trials)
             * - level: 装备等级（默认 1）
             * - floor: 副本层数（影响 world 装的 floorBoost，默认 1）
             * - trials: 采样次数（默认 20）
             */
            debugCompareDungeonVsNormal(level = 1, floor = 1, trials = 20) {
                try {
                    const sampleCount = Number(trials) || 20;
                    const lvl = Math.max(1, Number(level) || 1);
                    const team = { currentFloor: Math.max(1, Number(floor) || 1), members: [] };
                    // 如果存在冒险者列表，选取1名作为候选用于套装匹配判断
                    if (this.adventurers && this.adventurers.length > 0) team.members.push(this.adventurers[0]);

                    const stats = {
                        world: { count: 0, attack: 0, defense: 0, hp: 0, mp: 0, speed: 0, value: 0 },
                        normal: { count: 0, attack: 0, defense: 0, hp: 0, mp: 0, speed: 0, value: 0 }
                    };

                    const samples = [];
                    for (let i = 0; i < sampleCount; i++) {
                        const w = this.createDungeonEquipment(team, lvl);
                        // 基于 world 装的稀有度和部位，生成一个普通装备用于对比（同等级/同稀有度/同部位）
                        const rarityIndex = Math.max(0, Config.EQUIPMENT_RARITIES.indexOf(w.rarity));
                        const normal = this.createEquipment(lvl, rarityIndex, w.slot);

                        samples.push({ world: w, normal });

                        // 累加统计
                        stats.world.count++;
                        stats.world.attack += Number(w.attack) || 0;
                        stats.world.defense += Number(w.defense) || 0;
                        stats.world.hp += Number(w.hp) || 0;
                        stats.world.mp += Number(w.mp) || 0;
                        stats.world.speed += Number(w.speed) || 0;
                        stats.world.value += Number(w.value) || 0;

                        stats.normal.count++;
                        stats.normal.attack += Number(normal.attack) || 0;
                        stats.normal.defense += Number(normal.defense) || 0;
                        stats.normal.hp += Number(normal.hp) || 0;
                        stats.normal.mp += Number(normal.mp) || 0;
                        stats.normal.speed += Number(normal.speed) || 0;
                        stats.normal.value += Number(normal.value) || 0;
                    }

                    // 计算平均并打印明细
                    const avg = (s) => ({
                        attack: Math.round(s.attack / s.count),
                        defense: Math.round(s.defense / s.count),
                        hp: Math.round(s.hp / s.count),
                        mp: Math.round(s.mp / s.count),
                        speed: Math.round(s.speed / s.count),
                        value: Math.round(s.value / s.count)
                    });

                    const worldAvg = avg(stats.world);
                    const normalAvg = avg(stats.normal);

                    console.group('Debug: Dungeon(World) Equipment vs Normal Equipment');
                    console.log('Samples:', sampleCount, 'Level:', lvl, 'Floor:', team.currentFloor);
                    console.table({ World: worldAvg, Normal: normalAvg });
                    console.groupEnd();

                    // 也在游戏日志中写一条简短摘要，方便 UI 观察
                    this.addLogEntry(`调试比较：Level ${lvl} Floor ${team.currentFloor}，样本 ${sampleCount}，世界装平均价值 ${worldAvg.value}，普通装平均价值 ${normalAvg.value}`, 'info');

                    // 返回详细样本以便进一步检查（在控制台里查看）
                    return { samples, worldAvg, normalAvg };
                } catch (e) {
                    this.debugLog('debugCompareDungeonVsNormal 异常', e);
                    return null;
                }
            }

            /**
             * 计算冒险者实力评分
             * 根据冒险者的等级、属性和装备计算综合实力评分
             * 用于副本组队和实力展示
             * 
             * 评分计算公式：
             * 基础评分 = 等级 × 100
             * 属性评分 = (攻击×10 + 防御×8 + 生命×2 + 魔法×3 + 速度×15 + 暴击率×1000 + 暴击伤害×500)
             * 装备评分 = 所有装备价值总和 × 0.5
             * 套装评分 = 激活的套装数量 × 200
             * 最终评分 = 基础评分 + 属性评分 + 装备评分 + 套装评分
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {number} 实力评分
             */
            calculateAdventurerPowerScore(adventurer) {
                // 基础评分 = 等级 × 100
                const level = Number(adventurer && adventurer.level) || 1;
                let baseScore = level * 100;
                
                // 属性评分 = 各属性按不同系数转换为评分
                // 使用 Number(...) 并提供默认值，避免 NaN
                let statScore = 0;
                const attack = Number(adventurer && adventurer.attack) || 0;
                const defense = Number(adventurer && adventurer.defense) || 0;
                const maxHp = Number(adventurer && adventurer.maxHp) || 0;
                const maxMp = Number(adventurer && adventurer.maxMp) || 0;
                const speed = Number(adventurer && adventurer.speed) || 0;
                const critRate = Number(adventurer && adventurer.critRate) || 0;
                const critDamage = Number(adventurer && adventurer.critDamage) || 0;

                statScore += attack * 10;      // 攻击力系数
                statScore += defense * 8;      // 防御力系数
                statScore += maxHp * 2;        // 生命值系数
                statScore += maxMp * 3;        // 魔法值系数
                statScore += speed * 15;       // 速度系数
                statScore += critRate * 1000;  // 暴击率系数
                statScore += critDamage * 500; // 暴击伤害系数
                
                // 装备评分 = 所有装备价值总和 × 0.5
                let equipmentScore = 0;
                const eqs = adventurer && adventurer.equipment ? adventurer.equipment : {};
                for (const slot in eqs) {
                    const item = eqs[slot];
                    if (item) {
                        const val = Number(this.calculateEquipmentValue(item)) || 0;
                        equipmentScore += val * 0.5;
                    }
                }
                
                // 套装评分 = 激活的套装数量 × 200
                let setScore = 0;
                const setCounts = {};
                for (const slot in adventurer.equipment) {
                    const item = adventurer.equipment[slot];
                    if (item && item.set) {
                        setCounts[item.set] = (setCounts[item.set] || 0) + 1;
                    }
                }
                
                for (const setName in setCounts) {
                    const setConfig = Config.EQUIPMENT_SETS[setName];
                    if (setConfig && setCounts[setName] >= setConfig.pieces) {
                        setScore += 200;
                    }
                }
                
                // 最终评分 = 基础评分 + 属性评分 + 装备评分 + 套装评分
                const totalScore = Math.floor(baseScore + statScore + equipmentScore + setScore);
                adventurer.powerScore = Number.isFinite(totalScore) ? totalScore : 0;
                
                return adventurer.powerScore;
            }

            /**
             * 生成装备词缀 - 装备词缀系统
             * 根据装备稀有度生成相应数量和类型的词缀
             * 词缀系统为装备提供额外属性加成，增加装备多样性
             * 
             * 词缀数量规则：
             * - 白色：0个
             * - 绿色：1个
             * - 蓝色：2个
             * - 紫色：3个
             * - 橙色：3个
             * - 红色：4个
             * - 粉色：5个
             * - 金色：6个
             * - 彩虹：8个
             * 
             * @param {number} rarityIndex - 装备稀有度索引
             * @returns {Array} 词缀列表
             */
            /**
             * 生成装备词缀 - 装备词缀系统
             * 根据装备稀有度生成相应数量和类型的词缀
             * 确保词缀类型不重复增加装备多样性
             * 支持9种稀有度等级的词缀生成
             * 
             * 词缀数量规则：
             * - 白装(0)：0个词缀
             * - 绿装(1)：1个词缀
             * - 蓝装(2)：2个词缀
             * - 紫装(3)：3个词缀
             * - 橙装(4)：3个词缀
             * - 红装(5)：4个词缀
             * - 粉装(6)：5个词缀
             * - 金装(7)：6个词缀
             * - 彩虹装(8)：8个词缀
             * 
             * 生成流程：
             * 1. 根据稀有度索引确定词缀数量
             * 2. 获取所有可用词缀类型
             * 3. 创建已使用类型记录集合
             * 4. 循环生成指定数量词缀
             * 5. 随机选择未使用词缀类型
             * 6. 从该类型中随机选择具体词缀
             * 7. 记录使用避免重复
             * 8. 返回词缀列表
             * 
             * 防重复机制：
             * - 使用Set记录已选词缀类型
             * - 循环确保选择未使用类型
             * - 避免同类型词缀重复出现
             * - 保证词缀多样性
             * 
             * 随机性控制：
             * - 词缀类型随机选择
             * - 具体词缀随机选择
             * - 稀有度决定数量上限
             * - 保证每次生成都不同
             * 
             * @param {number} rarityIndex - 装备稀有度索引(0-8)
             * @returns {Array} 生成的词缀对象数组
             */
            generateEquipmentAffixes(rarityIndex) {
                // 初始化词缀数组
                const affixes = [];
                // 获取所有词缀类型
                const affixTypes = Object.keys(Config.EQUIPMENT_AFFIXES);

                // 根据稀有度决定词缀数量
                let affixCount = 0;
                if (rarityIndex >= 1) affixCount = 1; // 绿色装备1个词缀
                if (rarityIndex >= 2) affixCount = 2; // 蓝色装备2个词缀
                if (rarityIndex >= 3) affixCount = 3; // 紫色装备3个词缀
                if (rarityIndex >= 5) affixCount = 4; // 红色装备4个词缀
                if (rarityIndex >= 6) affixCount = 5; // 粉色装备5个词缀
                if (rarityIndex >= 7) affixCount = 6; // 金色装备6个词缀
                if (rarityIndex >= 8) affixCount = 8; // 彩虹装备8个词缀

                // 记录已使用的词缀类型，避免重复
                const usedTypes = new Set();
                // 生成指定数量的词缀
                for (let i = 0; i < affixCount && usedTypes.size < affixTypes.length; i++) {
                    let type;
                    // 确保不重复使用同类型词缀
                    // 添加安全计数器，避免无限循环
                    let safetyCounter = 0;
                    do {
                        type = affixTypes[Math.floor(Math.random() * affixTypes.length)];
                        safetyCounter++;
                        // 如果尝试次数过多，跳出循环
                        if (safetyCounter > 100) break;
                    } while (usedTypes.has(type));
                    
                    // 记录已使用的词缀类型
                    usedTypes.add(type);
                    // 从该类型中随机选择一个具体词缀
                    const affix = Config.EQUIPMENT_AFFIXES[type][Math.floor(Math.random() * Config.EQUIPMENT_AFFIXES[type].length)];
                    // 添加到词缀列表
                    affixes.push(affix);
                }

                // 返回生成的词缀列表
                return affixes;
            }

            /**
             * 应用词缀效果 - 装备词缀属性系统
             * 根据装备的词缀列表为装备添加相应的属性加成
             * 词缀按类型分类，不同词缀提供不同属性加成
             * 支持词缀等级机制和特殊效果生成
             * 
             * 词缀等级机制：
             * - 每两个词缀为一个等级组
             * - 高等级词缀提供更强的属性加成
             * - 加成倍数 = 1 + (词缀等级-1) × 0.5
             * 
             * 词缀分类和效果：
             * 1. 攻击类：增加攻击力(锋利、致命、狂暴、毁灭)
             * 2. 元素类：增加攻击力并提供元素伤害效果(燃烧、雷霆)
             * 3. 防御类：增加防御力(坚固、守护、钢铁、不灭)
             * 4. 生命防御类：增加防御力和生命值(神圣、大地)
             * 5. 生命类：增加生命值(活力、生命、永恒、重生)
             * 6. 恢复类：大幅增加生命值并提供恢复效果(恢复、疗愈)
             * 7. 速度类：增加移动速度(迅捷、轻灵、风行、幻影)
             * 8. 瞬移类：增加移动速度并提供瞬移效果(闪电、瞬移)
             * 9. 暴击类：增加暴击率和暴击伤害(暴击、必杀、死神、狩猎)
             * 10. 致命类：大幅增加暴击率和暴击伤害(致命、给命)
             * 11. 魔法类：增加魔法值(智慧、奥术、魔力)
             * 12. 元素魔法类：大幅增加魔法值并提供魔法攻击力(神秘、元素、禁咒)
             * 13. 吸血类：提供吸血效果(吸血、吸收)
             * 14. 反射类：提供反射伤害效果(反射、反击)
             * 15. 神圣类：综合属性加成和特殊效果(圣洁、光明、天使、神的)
             * 16. 传说类：顶级属性加成(传说、神话、神圣)
             * 
             * 属性加成机制：
             * - 基础加成 = 装备等级 × 随机系数 × 倍数
             * - 特殊效果 = 固定文本描述 + 数值计算
             * - 概率性效果 = 随机数判断触发
             * - 多重效果可叠加生效
             * 
             * 数据处理：
             * - 词缀索引决定等级分组
             * - 向下取整保证属性为整数
             * - 随机系数增加装备差异性
             * - 特殊效果覆盖机制
             * 
             * @param {Object} equipment - 装备对象
             * @param {Array} affixes - 词缀列表
             */
            applyAffixes(equipment, affixes) {
                // 遍历所有词缀并应用效果
                affixes.forEach((affix, index) => {
                    // 计算词缀等级 - 每两个词缀为一个等级组
                    const tier = Math.floor(index / 2) + 1;
                    // 计算加成倍数 - 高等级词缀提供更强加成
                    const multiplier = 1 + (tier - 1) * 0.5;
                    
                    // 攻击类词缀 - 增加攻击力
                    if (affix.includes('锋利') || affix.includes('致命') || affix.includes('狂暴') || affix.includes('毁灭')) {
                        equipment.attack += Math.floor(equipment.level * (1 + Math.random()) * multiplier);
                    }
                    // 元素攻击词缀 - 增加攻击力并提供元素伤害效果
                    if (affix.includes('燃烧') || affix.includes('雷霆')) {
                        equipment.attack += Math.floor(equipment.level * 1.5 * multiplier);
                        equipment.special = `元素伤害：额外造成${Math.floor(equipment.level * 0.5 * multiplier)}伤害`;
                    }
                    
                    // 防御类词缀 - 增加防御力
                    if (affix.includes('坚固') || affix.includes('守护') || affix.includes('钢铁') || affix.includes('不灭')) {
                        equipment.defense += Math.floor(equipment.level * (1 + Math.random()) * multiplier);
                    }
                    // 生命防御词缀 - 增加防御力和生命值
                    if (affix.includes('神圣') || affix.includes('大地')) {
                        equipment.defense += Math.floor(equipment.level * 1.2 * multiplier);
                        equipment.hp += Math.floor(equipment.level * 3 * multiplier);
                    }
                    
                    // 生命类词缀 - 增加生命值
                    if (affix.includes('活力') || affix.includes('生命') || affix.includes('永恒') || affix.includes('重生')) {
                        equipment.hp += Math.floor(equipment.level * 5 * multiplier);
                    }
                    // 恢复类词缀 - 大幅增加生命值并提供恢复效果
                    if (affix.includes('恢复') || affix.includes('疗愈')) {
                        equipment.hp += Math.floor(equipment.level * 8 * multiplier);
                        equipment.special = `生命恢复：每秒恢复${Math.floor(equipment.level * 0.2 * multiplier)}生命值`;
                    }
                    
                    // 速度类词缀 - 增加移动速度
                    if (affix.includes('迅捷') || affix.includes('轻灵') || affix.includes('风行') || affix.includes('幻影')) {
                        equipment.speed += Math.floor(equipment.level * 0.5 * multiplier);
                    }
                    // 瞬移类词缀 - 增加移动速度并提供瞬移效果
                    if (affix.includes('闪电') || affix.includes('瞬移')) {
                        equipment.speed += Math.floor(equipment.level * 0.8 * multiplier);
                        equipment.special = `瞬间移动：攻击后有几率瞬间移动到目标身后`;
                    }
                    
                    // 暴击类词缀 - 增加暴击率和暴击伤害
                    if (affix.includes('暴击') || affix.includes('必杀') || affix.includes('死神') || affix.includes('狩猎')) {
                        equipment.critRate += 0.02 * multiplier;
                        equipment.critDamage += 0.1 * multiplier;
                    }
                    // 致命类词缀 - 大幅增加暴击率和暴击伤害
                    if (affix.includes('致命') || affix.includes('给命')) {
                        equipment.critRate += 0.03 * multiplier;
                        equipment.critDamage += 0.2 * multiplier;
                    }
                    
                    // 魔法类词缀 - 增加魔法值
                    if (affix.includes('智慧') || affix.includes('奥术') || affix.includes('魔力')) {
                        equipment.mp += Math.floor(equipment.level * 3 * multiplier);
                    }
                    // 元素魔法词缀 - 大幅增加魔法值并提供魔法攻击力
                    if (affix.includes('神秘') || affix.includes('元素') || affix.includes('禁咒')) {
                        equipment.mp += Math.floor(equipment.level * 5 * multiplier);
                        equipment.attack += Math.floor(equipment.level * 0.5 * multiplier); // 魔法攻击力
                    }
                    
                    // 吸血类词缀 - 提供吸血效果
                    if (affix.includes('吸血') || affix.includes('吸收')) {
                        equipment.special = `吸血效果：攻击时恢复${Math.floor(equipment.level * 0.3 * multiplier)}生命值`;
                    }
                    // 反射类词缀 - 提供反射伤害效果
                    if (affix.includes('反射') || affix.includes('反击')) {
                        equipment.special = `反射伤害：受到攻击时反射${Math.floor(equipment.level * 0.8 * multiplier)}伤害`;
                    }
                    
                    // 神圣系词缀 - 综合属性加成和特殊效果
                    if (affix.includes('圣洁') || affix.includes('光明') || affix.includes('天使') || affix.includes('神的')) {
                        equipment.defense += Math.floor(equipment.level * 0.8 * multiplier);
                        equipment.hp += Math.floor(equipment.level * 4 * multiplier);
                        equipment.mp += Math.floor(equipment.level * 2 * multiplier);
                        // 30%几率获得神圣庇护效果
                        if (Math.random() < 0.3) {
                            equipment.special = `神圣庇护：受到攻击时有几率获得无敌状态`;
                        }
                    }
                    
                    // 传说系词缀 - 顶级属性加成
                    if (affix.includes('传说') || affix.includes('神话') || affix.includes('神圣')) {
                        equipment.attack += Math.floor(equipment.level * 1.5 * multiplier);
                        equipment.defense += Math.floor(equipment.level * 1.2 * multiplier);
                        equipment.hp += Math.floor(equipment.level * 6 * multiplier);
                        equipment.critRate += 0.05 * multiplier;
                        equipment.critDamage += 0.3 * multiplier;
                    }
                });
            }

            /**
             * 获取装备稀有度CSS类名 - 装备显示系统
             * 根据装备稀有度返回对应的CSS类名
             * 用于装备显示时的颜色和样式区分
             * 支持所有稀有度等级的样式映射
             * 
             * 类名生成规则：
             * - 格式：rarity-稀有度小写英文名
             * - 特殊字符：移除所有非字母数字字符
             * - 默认值：未找到稀有度返回rarity-white
             * - 样式定义：在CSS中定义对应颜色
             * 
             * 稀有度映射：
             * - 白装：rarity-white
             * - 绿装：rarity-green
             * - 蓝装：rarity-blue
             * - 紫装：rarity-purple
             * - 橙装：rarity-orange
             * - 红装：rarity-red
             * - 粉装：rarity-pink
             * - 金装：rarity-golden
             * - 彩虹装：rarity-rainbow
             * 
             * 字符处理：
             * - 转换为小写保证一致性
             * - 移除非字母数字字符
             * - 保证类名符合CSS规范
             * - 避免特殊字符导致样式失效
             * 
             * @param {string} rarity - 装备稀有度名称
             * @returns {string} 对应的CSS类名
             */
            // 获取装备稀有度颜色CSS类名
            getRarityClass(rarity) {
                const rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(rarity);
                if (rarityIndex >= 0) {
                    return `rarity-${Config.EQUIPMENT_RARITIES[rarityIndex].toLowerCase().replace(/[^a-z0-9]/g, '')}`;
                }
                return 'rarity-white';
            }
            
            // 获取装备稀有度颜色值
            getRarityColor(rarity) {
                return Config.EQUIPMENT_RARITY_COLORS[rarity] || '#ffffff';
            }

            createMonster() {
                if (this.monsters.length >= Config.MONSTER_MAX_COUNT) return null;

                const type = Config.MONSTER_TYPES[Math.floor(Math.random() * Config.MONSTER_TYPES.length)];
                const rank = Config.MONSTER_RANKS[Math.floor(Math.random() * Config.MONSTER_RANKS.length)];
                const behavior = Config.MONSTER_BEHAVIORS[Math.floor(Math.random() * Config.MONSTER_BEHAVIORS.length)];
                const attribute = Object.keys(Config.MONSTER_ATTRIBUTES)[Math.floor(Math.random() * Object.keys(Config.MONSTER_ATTRIBUTES).length)];

                // 根据冒险者平均等级生成怪物等级 - 修复等级计算错误
                const avgLevel = this.adventurers.length > 0 ?
                    Math.floor(this.adventurers.reduce((sum, a) => sum + a.level, 0) / this.adventurers.length) : 1;

                // 生成与冒险者等级匹配的怪物，允许一定范围的等级差异
                // 神话怪物可以比冒险者等级高很多
                let level = Math.max(1, avgLevel + Math.floor(Math.random() * 5) - 2);
                
                // 根据稀有度调整等级范围
                if (rank === '神话') {
                    level = Math.max(1, avgLevel + Math.floor(Math.random() * 10)); // 神话怪物等级更高
                } else if (rank === '传说') {
                    level = Math.max(1, avgLevel + Math.floor(Math.random() * 7) - 1);
                } else if (rank === '首领') {
                    level = Math.max(1, avgLevel + Math.floor(Math.random() * 5));
                }

                // 根据rank调整等级和属性
                let levelMod = 0;
                let statMod = 1;
                let dropRateMod = 1;
                let expMod = 1;

                switch(rank) {
                    case '精英':
                        levelMod = 0;
                        statMod = 1.5;
                        dropRateMod = 1.3;
                        expMod = 1.5;
                        break;
                    case '首领':
                        levelMod = 0;
                        statMod = 2.5;
                        dropRateMod = 2.0;
                        expMod = 2.5;
                        break;
                    case '传说':
                        levelMod = 0;
                        statMod = 4.0;
                        dropRateMod = 3.0;
                        expMod = 4.0;
                        break;
                    case '神话':
                        levelMod = 1;
                        statMod = 6.0;
                        dropRateMod = 5.0;
                        expMod = 6.0;
                        break;
                }

                // 根据行为模式进一步调整属性
                switch(behavior) {
                    case '狂暴':
                        statMod *= 1.2;
                        break;
                    case '群体':
                        statMod *= 1.3;
                        dropRateMod *= 1.2;
                        break;
                    case '飞行':
                        statMod *= 1.3; // 飞行怪物通常更强
                        break;
                    case '潜行':
                        statMod *= 0.8;
                        dropRateMod *= 1.5; // 难以发现的怪物掉落更好
                        break;
                    case '召唤':
                        statMod *= 0.7;
                        dropRateMod *= 0.5; // 召唤物掉落较少
                        break;
                    case '自爆':
                        statMod *= 1.5; // 自爆怪物通常有更高的攻击力
                        break;
                    case '分裂':
                        statMod *= 0.8;
                        break;
                    case '变形':
                        statMod *= 1.1;
                        break;
                    case '传送':
                        statMod *= 1.2; // 传送怪物通常更灵活
                        break;
                }

                level += levelMod;

                // 属性加成
                const attrBonus = Config.MONSTER_ATTRIBUTES[attribute].bonus;
                let baseHp = 50 * level * statMod;
                let baseAttack = 5 * level * statMod;
                let baseDefense = 3 * level * statMod;
                let baseSpeed = 1 + Math.random() * 2;

                // 应用属性加成
                if (attrBonus.hp) baseHp *= attrBonus.hp;
                if (attrBonus.attack) baseAttack *= attrBonus.attack;
                if (attrBonus.defense) baseDefense *= attrBonus.defense;
                if (attrBonus.speed) baseSpeed *= attrBonus.speed;
                if (attrBonus.allStats) {
                    baseHp *= attrBonus.allStats;
                    baseAttack *= attrBonus.allStats;
                    baseDefense *= attrBonus.allStats;
                }
                
                // 平衡性调整：降低攻击防御，增加生命值
                baseAttack *= 0.5; // 攻击力降低一半
                baseDefense *= 0.5; // 防御力降低一半
                baseHp *= 2; // 生命值增长一倍
                
                // 根据稀有度进一步调整属性
                if (rank === '神话') {
                    baseHp *= 1.5;
                    baseAttack *= 1.3;
                    baseDefense *= 1.3;
                } else if (rank === '传说') {
                    baseHp *= 1.3;
                    baseAttack *= 1.2;
                    baseDefense *= 1.2;
                }

                    // 使用半集中式位置生成，让怪物更容易被发现
                const scatteredPos = this.generateSemiConcentratedPosition(this.gameAreaWidth, this.gameAreaHeight, 100);
                
                const monster = {
                    id: Date.now() + Math.random(),
                    type,
                    rank,
                    behavior,
                    attribute,
                    level,
                    hp: Math.floor(baseHp),
                    maxHp: Math.floor(baseHp),
                    attack: Math.floor(baseAttack),
                    defense: Math.floor(baseDefense),
                    speed: baseSpeed,
                    critRate: attrBonus.critRate || 0,
                    rewardGold: Math.floor(10 * level * (levelMod + 1) * expMod),
                    rewardExp: Math.floor(15 * level * (levelMod + 1) * expMod),
                    dropRate: 0.3 * dropRateMod,
                    equipmentDropLevel: level,
                    equipmentDropRarity: Math.min(8, Math.floor(level / 5) + Math.floor(Math.random() * 3)),
                    x: scatteredPos.x,
                    y: scatteredPos.y,
                    direction: Math.random() * Math.PI * 2,
                    targetX: null,
                    targetY: null,
                    lastDirectionChange: Date.now(),
                    aggroRadius: 80 + level * 2,
                    skills: this.generateMonsterSkills(type, rank, level),
                    lastSkillUse: 0,
                    state: 'idle', // idle, patrol, chase, attack, skill
                    spawnTime: Date.now() // 怪物生成时间戳
                };

                this.monsters.push(monster);
                this.lastMonsterSpawn = `${attribute}${rank}${type} Lv.${level}`;
                const lastSpawnEl = document.getElementById('last-spawn');
                if (lastSpawnEl) lastSpawnEl.textContent = this.lastMonsterSpawn;
                
                // 添加日志记录
                this.addLogEntry(`生成了${attribute}${rank}${type} (Lv.${level})`, 'info');

                return monster;
            }

            /**
             * 生成怪物技能 - 怪物AI系统
             * 根据怪物类型、稀有度和等级生成技能列表
             * 支持18种不同怪物类型的专属技能
             * 技能数量随稀有度和等级增长
             * 
             * 怪物技能配置：
             * - 哥布林：怒咮、投石、群体召唤
             * - 兽人：野蒷冲锋、厲吓、狂暴
             * - 骷髅：毒牢、死亡凝视、骨甲
             * - 蜘蛛：网络束缚、剧毒、连击
             * - 狼：咄叫、撕裂、快速移动
             * - 巨魔：巨力冲击、震地、投石雨
             * - 元素生物：元素爆裂、元素屏障、元素融合
             * - 龙类：龙息、龙威、飞行攻击
             * - 史莱姆：分裂、弹跳、吸收
             * - 蝙蝠：超声波、吸血、闪避
             * - 僵尸：传染、不死、腫气
             * - 幽灵：穿透、恐惧、魔法吸收
             * - 恶魔：火焰、诅咒、召唤小魔
             * - 天使：治疗、光之裁决、神圣光环
             * - 石像鬼：石化、飞行、爪击
             * - 狮鹫：俯冲、翼击、鹰眼
             * - 九头蛇：多头攻击、毒息、再生
             * - 凤凰：涅槃、火焰翼膀、圣火
             * 
             * 技能数量规则：
             * - 普通：1个技能
             * - 精英：2个技能
             * - 首领：3个技能
             * - 传说：4个技能
             * - 神话：5个技能
             * - 20级以上：额外+1技能
             * - 50级以上：额外+1技能
             * 
             * 生成机制：
             * - 随机选择可用技能
             * - 避免重复技能
             * - 数量不超过可用技能总数
             * - 默认技能为普通攻击
             * 
             * 数据处理：
             * - 技能去重处理
             * - 数量限制控制
             * - 随机性保证多样性
             * - 类型匹配确保合理性
             * 
             * @param {string} type - 怪物类型
             * @param {string} rank - 怪物稀有度
             * @param {number} level - 怪物等级
             * @returns {Array} 技能名称数组
             */
            generateMonsterSkills(type, rank, level) {
                const skills = [];
                
                // 根据怪物类型生成技能
                const typeSkills = {
                    '哥布林': ['怒咮', '投石', '群体召唤'],
                    '兽人': ['野蒷冲锋', '厲吓', '狂暴'],
                    '骷髅': ['毒牢', '死亡凝视', '骨甲'],
                    '蜘蛛': ['网络束缚', '剧毒', '连击'],
                    '狼': ['咄叫', '撕裂', '快速移动'],
                    '巨魔': ['巨力冲击', '震地', '投石雨'],
                    '元素生物': ['元素爆裂', '元素屏障', '元素融合'],
                    '龙类': ['龙息', '龙威', '飞行攻击'],
                    '史莱姆': ['分裂', '弹跳', '吸收'],
                    '蝙蝠': ['超声波', '吸血', '闪避'],
                    '僵尸': ['传染', '不死', '腫气'],
                    '幽灵': ['穿透', '恐惧', '魔法吸收'],
                    '恶魔': ['火焰', '诅咒', '召唤小魔'],
                    '天使': ['治疗', '光之裁决', '神圣光环'],
                    '石像鬼': ['石化', '飞行', '爪击'],
                    '狮鹫': ['俯冲', '翼击', '鹰眼'],
                    '九头蛇': ['多头攻击', '毒息', '再生'],
                    '凤凰': ['涅槃', '火焰翼膀', '圣火'],
                    '德鲁伊': ['自然之力', '荆棘护甲', '生命恢复'],
                    '独眼巨人': ['重锤打击', '地震波', '投掷巨石'],
                    '牛头人': ['冲撞', '狂暴', '战吼'],
                    '熊人': ['重击', '咆哮', '防御姿态'],
                    '剑齿虎': ['撕裂', '伏击', '迅捷'],
                    '巨型章鱼': ['触手缠绕', '墨汁喷射', '水下呼吸'],
                    '海怪': ['海啸', '深海诅咒', '水元素召唤'],
                    '雪怪': ['冰霜新星', '暴风雪', '冰甲术'],
                    '火元素': ['烈焰风暴', '熔岩护盾', '火焰箭'],
                    '水元素': ['水牢', '治疗之雨', '冰冻术'],
                    '土元素': ['地震术', '石肤术', '石化凝视'],
                    '风元素': ['龙卷风', '迅捷术', '风刃'],
                    '机械构造体': ['激光射击', '能量护盾', '自爆'],
                    '虚空行者': ['虚空撕裂', '传送术', '暗影步'],
                    '时间扭曲者': ['时间停止', '时间回溯', '加速术'],
                    '混沌魔物': ['混沌冲击', '混乱术', '变形术'],
                    '梦境吞噬者': ['催眠术', '噩梦', '精神控制'],
                    '星界生物': ['星辰坠落', '星光护盾', '宇宙射线'],
                    '暗影刺客': ['背刺', '隐身术', '毒刃'],
                    '熔岩巨人': ['熔岩喷发', '火焰护盾', '地震术'],
                    '冰霜领主': ['冰霜之环', '寒冰护盾', '暴风雪'],
                    '雷霆使者': ['雷电链', '闪电风暴', '雷神之锤'],
                    '森林守护者': ['荆棘缠绕', '自然治愈', '召唤树人'],
                    '沙漠之王': ['沙尘暴', '流沙陷阱', '烈日灼烧'],
                    '深海巨兽': ['深海漩涡', '水压冲击', '海妖之歌'],
                    '天空霸主': ['风暴之翼', '雷电俯冲', '云层遮蔽'],
                    '地下领主': ['地震术', '岩石投掷', '洞穴召唤'],
                    '瘟疫传播者': ['瘟疫之云', '疾病传播', '腐化术'],
                    '死亡骑士': ['死亡之握', '恐惧光环', '亡灵召唤'],
                    '灵魂收割者': ['灵魂吸取', '死亡之镰', '灵魂束缚'],
                    '秩序守护者': ['正义审判', '秩序之光', '守护结界']
                };
                
                const availableSkills = typeSkills[type] || ['普通攻击'];
                
                // 根据等级和稀有度决定技能数量
                let skillCount = 1;
                if (rank === '精英') skillCount = 2;
                else if (rank === '首领') skillCount = 3;
                else if (rank === '传说') skillCount = 4;
                else if (rank === '神话') skillCount = 5;
                
                if (level >= 20) skillCount++;
                if (level >= 50) skillCount++;
                
                for (let i = 0; i < Math.min(skillCount, availableSkills.length); i++) {
                    const skill = availableSkills[Math.floor(Math.random() * availableSkills.length)];
                    if (!skills.includes(skill)) {
                        skills.push(skill);
                    }
                }
                
                return skills;
            }

            /**
             * 更新资源显示 - 优化版本
             * 减少不必要的DOM更新，提高性能
             */
            /**
             * 更新资源显示方法
             * 更新界面上所有资源数值的显示，包括金币、魅力值等
             * 使用缓存和值变化检测来优化性能，避免不必要的DOM更新
             */
            /**
             * 更新资源显示 - UI显示系统
             * 实时更新游戏核心资源的显示状态
             * 包括金币、魅力值等核心资源
             * 
             * 性能优化策略：
             * 1. 缓存DOM元素引用，避免重复查询
             * 2. 只在数值变化时更新，避免不必要的DOM操作
             * 3. 金币数值向下取整显示（避免小数点）
             * 
             * 资源说明：
             * - 金币：游戏主要货币，用于建造和购买
             * - 魅力值：影响村庄吸引力和特殊事件触发
             * 
             * 更新机制：
             * - 与游戏主循环同步更新
             * - 值变化检测避免冗余渲染
             * - DOM元素存在性检查确保安全更新
             */
            updateResourceDisplay() {
                // 使用缓存避免重复的getElementById调用，提高性能
                const elements = {
                    gold: document.getElementById('gold-value'),    // 金币显示元素
                    charm: document.getElementById('charm-value')   // 魅力值显示元素
                };
                
                // 只有当元素存在且值发生变化时才更新，避免不必要的DOM操作
                if (elements.gold) {
                    const goldValue = Math.floor(this.gold);  // 金币值取整数
                    if (elements.gold.textContent != goldValue) {
                        elements.gold.textContent = goldValue;
                    }
                }
                
                if (elements.charm) {
                    // 魅力值直接显示，只有在变化时才更新
                    if (elements.charm.textContent != this.charm) {
                        elements.charm.textContent = this.charm;
                    }
                }
            }

            /**
             * 更新称号显示 - UI显示系统
             * 实时更新当前称号及其效果的显示状态
             * 包括称号名称和各种属性加成效果
             * 
             * 显示特点：
             * 1. 显示当前获得的称号名称
             * 2. 列出所有称号效果及其数值
             * 3. 支持多种类型的属性加成显示
             * 4. 当无效果时显示"无特殊效果"提示
             * 
             * 称号效果类型：
             * - 金币获取加成：提高金币收入
             * - 招募速度加成：加快冒险者招募
             * - 攻击力加成：提升战斗能力
             * - 掉落率加成：提高装备获取概率
             * - 装备品质加成：提升装备生成质量
             * - 税率加成：增加建筑收入
             * - 建筑收入加成：提高建筑产出
             * - 全属性加成：全面提升各项属性
             * - 最大冒险者加成：增加可招募冒险者上限
             * 
             * 更新机制：
             * - 与游戏主循环同步更新
             * - DOM元素存在性检查确保安全更新
             * - HTML格式化显示支持换行效果
             */
            updateTitleDisplay() {
                const titleElement = document.getElementById('current-title');
                const effectsElement = document.getElementById('title-effects');

                if (titleElement) titleElement.textContent = this.currentTitle;

                let effectsText = '';
                for (const effect in this.titleEffects) {
                    switch(effect) {
                        case 'goldBonus':
                            effectsText += `金币获取 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'recruitSpeed':
                            effectsText += `冒险者招募速度 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'attackBonus':
                            effectsText += `攻击力 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'dropRate':
                            effectsText += `掉落率 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'equipmentQuality':
                            effectsText += `装备品质 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'taxRate':
                            effectsText += `税率 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'buildingIncome':
                            effectsText += `建筑收入 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'allStats':
                            effectsText += `全属性 +${Math.floor(this.titleEffects[effect] * 100)}%<br>`;
                            break;
                        case 'maxAdventurers':
                            effectsText += `最大冒险者 +${this.titleEffects[effect]}<br>`;
                            break;
                    }
                }

                if (effectsElement) effectsElement.innerHTML = effectsText || '无特殊效果';
            }

            /**
             * 检查称号解锁条件 - 游戏进度系统
             * 定期检查所有未解锁称号的解锁条件
             * 当满足条件时自动解锁并应用称号效果
             * 
             * 解锁机制：
             * 1. 遍历所有配置的称号
             * 2. 跳过已解锁的称号
             * 3. 检查解锁条件是否满足
             * 4. 满足条件时执行解锁流程
             * 
             * 解锁流程：
             * 1. 将称号添加到已解锁列表
             * 2. 设置为当前称号
             * 3. 应用称号效果属性
             * 4. 更新称号显示界面
             * 5. 显示成就通知
             * 6. 添加日志记录
             * 
             * 称号系统特点：
             * - 自动检测解锁条件
             * - 一次性解锁机制
             * - 多种条件类型支持
             * - 解锁后立即生效
             * - 视觉和日志反馈
             */
            checkTitleUnlocks() {
                for (const titleName in Config.TITLES) {
                    if (this.unlockedTitles.includes(titleName)) continue;

                    const title = Config.TITLES[titleName];
                    if (title.condition(this)) {
                        this.unlockedTitles.push(titleName);
                        this.currentTitle = titleName;
                        this.titleEffects = title.effects;
                        this.updateTitleDisplay();
                        this.showAchievement(`获得称号：${titleName}`, '恭喜解锁新称号！');
                        this.addLogEntry(`获得称号：${titleName}`, 'success');
                    }
                }
            }

            /**
             * 显示成就通知 - UI反馈系统
             * 在屏幕中央显示成就解锁的弹窗通知
             * 支持队列机制处理连续解锁的多个成就
             * 同时将成就信息记录到游戏日志中
             * 
             * 显示特点：
             * 1. 屏幕中央弹窗显示
             * 2. 显示时间3秒
             * 3. 连续成就队列处理
             * 4. 500ms间隔显示下一个
             * 5. 成功状态日志记录
             * 
             * 队列机制：
             * 1. 成就推入显示队列
             * 2. 检查是否正在显示成就
             * 3. 未显示时启动处理流程
             * 4. 显示完成后延迟处理下一个
             * 5. 队列清空后重置状态
             * 
             * 视觉反馈：
             * - 弹窗元素显示控制
             * - 标题和描述内容更新
             * - 显示/隐藏状态切换
             * - 时间控制的自动关闭
             * 
             * @param {string} title - 成就标题
             * @param {string} description - 成就描述
             */
            showAchievement(title, description) {
                // 将成就添加到队列中，支持连续显示多个成就
                this.achievementQueue.push({ title, description });
                // 如果当前没有正在显示成就，则开始处理队列
                if (!this.isShowingAchievement) {
                    this.processAchievementQueue();
                }
                // 记录到游戏日志
                this.addLogEntry(`${title}: ${description}`, 'success');
            }

            /**
             * 处理成就显示队列 - UI队列系统
             * 按顺序处理成就显示队列中的项目
             * 实现连续成就的间隔显示效果
             * 确保用户能清楚看到每个成就
             * 
             * 处理流程：
             * 1. 检查队列是否为空
             * 2. 设置显示状态标志
             * 3. 取出队列首个成就
             * 4. 更新弹窗内容显示
             * 5. 控制弹窗显示状态
             * 6. 设置定时器控制显示时间
             * 7. 显示结束后延迟处理下一个
             * 
             * 时间控制：
             * - 成就显示时长：3000ms
             * - 成就间隔时长：500ms
             * - 状态重置延迟：避免视觉冲突
             * 
             * DOM操作安全：
             * - 所有元素获取后检查存在性
             * - 避免对不存在元素的操作
             * - 稳定的显示/隐藏控制
             */
            processAchievementQueue() {
                if (this.achievementQueue.length === 0) {
                    this.isShowingAchievement = false;
                    return;
                }

                this.isShowingAchievement = true;
                const achievement = this.achievementQueue.shift();

                const popup = document.getElementById('achievement-popup');
                const titleEl = document.getElementById('achievement-title');
                const descEl = document.getElementById('achievement-desc');
                
                if (titleEl) titleEl.textContent = achievement.title;
                if (descEl) descEl.textContent = achievement.description;

                if (popup) popup.style.display = 'block';

                setTimeout(() => {
                    if (popup) popup.style.display = 'none';
                    setTimeout(() => {
                        this.processAchievementQueue();
                    }, 500);
                }, 3000);
            }

            /**
             * 更新冒险者相关的UI显示 - 页签系统集成
             * 更新概览页签中的冒险者数量显示和冒险者页签数据
             * 适配新的页签系统，替代原有的列表显示方式
             * 
             * 更新内容：
             * 1. 概览页签中的冒险者数量显示
             * 2. 冒险者页签的详细数据
             * 
             * 设计考虑：
             * - 适配页签系统的UI结构
             * - 应用称号效果对最大冒险者数量的影响
             * - 保持UI数据的实时性
             * 
             */
            updateAdventurerList() {
                // 更新概览页签中的冒险者数量显示
                const maxAdventurers = Config.MAX_ADVENTURERS + (this.titleEffects.maxAdventurers || 0);
                
                // 尝试更新概览页签中的数量（如果存在的话）
                const overviewCount = document.getElementById('overview-adventurer-count');
                if (overviewCount) {
                    overviewCount.textContent = `${this.adventurers.length}/${maxAdventurers}`;
                }
                
                // 更新冒险者页签数据
                this.updateAdventurersTab();
            }

            /**
             * 显示冒险者信息提示框 - UI交互系统
             * 当鼠标悬停在冒险者元素上时显示详细信息提示框
             * 提供冒险者的实时状态信息，便于玩家了解情况
             * 
             * 显示信息：
             * 1. 基本信息（姓名、等级、职业）
             * 2. 生命值和魔法值状态
             * 3. 饥饿值状态
             * 4. 战斗属性（攻击、防御、速度）
             * 5. 暴击属性
             * 6. 当前状态（正常/受伤/饥饿/死亡）
             * 
             * 状态判断逻辑：
             * - 死亡中：state为'dead'
             * - 受伤：生命值低于30%
             * - 饥饿：饥饿值低于30
             * - 正常：其他情况
             * 
             * @param {Event} e - 鼠标事件对象
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 显示冒险者信息提示框 - UI交互系统
             * 当鼠标悬停在冒险者元素上时显示详细信息提示框
             * 提供冒险者的实时状态信息，便于玩家了解情况
             * 支持丰富的状态显示和属性信息展示
             * 
             * 显示信息：
             * 1. 基本信息（姓名、等级、职业）
             * 2. 生命值和魔法值状态
             * 3. 饥饿值状态
             * 4. 战斗属性（攻击、防御、速度）
             * 5. 暴击属性
             * 6. 当前状态（正常/受伤/饥饿/死亡）
             * 
             * 状态判断逻辑：
             * - 死亡中：state为'dead'
             * - 受伤：生命值低于30%
             * - 饥饿：饥饿值低于30
             * - 正常：其他情况
             * 
             * 界面设计特点：
             * - 使用HTML模板动态生成内容
             * - 数值显示进行取整处理提高可读性
             * - 百分比数值格式化显示
             * - 状态文本直观易懂
             * - 实时数据确保准确性
             * 
             * 显示控制机制：
             * - 通过CSS display属性控制显示/隐藏
             * - 提示框元素复用避免频繁创建
             * - 内容动态更新保持实时性
             * - 与hideTooltip方法配合使用
             * 
             * @param {Event} e - 鼠标事件对象
             * @param {Object} adventurer - 冒险者对象
             */
            showTooltip(e, adventurer) {
                const tooltip = document.getElementById('tooltip');
                let statusText = '正常';
                if (adventurer.state === 'dead') statusText = '死亡中';
                else if (adventurer.hp < adventurer.maxHp * 0.3) statusText = '受伤';
                else if (adventurer.hunger < 30) statusText = '饥饿';

                tooltip.innerHTML = `
                    <div class="tooltip-name">${adventurer.name} - Lv.${adventurer.level} ${adventurer.class}</div>
                    <div class="tooltip-stats">
                        <div>HP: ${Math.floor(adventurer.hp)}/${adventurer.maxHp}</div>
                        <div>MP: ${Math.floor(adventurer.mp)}/${adventurer.maxMp}</div>
                        <div>饥饿: ${Math.floor(adventurer.hunger)}/${adventurer.maxHunger}</div>
                        <div>攻击: ${adventurer.attack}</div>
                        <div>防御: ${adventurer.defense}</div>
                        <div>速度: ${adventurer.speed}</div>
                        <div>暴击率: ${(adventurer.critRate * 100).toFixed(1)}%</div>
                        <div>暴击伤害: ${(adventurer.critDamage * 100).toFixed(0)}%</div>
                        <div>状态: ${statusText}</div>
                    </div>
                `;
                tooltip.style.display = 'block';
            }

            /**
             * 隐藏信息提示框 - UI交互系统
             * 隐藏当前显示的信息提示框
             * 与showTooltip方法配合使用，完成提示框的显示/隐藏交互
             * 确保界面整洁避免信息干扰
             * 
             * 隐藏机制：
             * 1. 通过CSS display属性控制隐藏
             * 2. 元素仍然存在于DOM中便于复用
             * 3. 与显示方法形成完整交互循环
             * 4. 简单高效避免复杂操作
             * 
             * 设计考虑：
             * - 隐藏而非销毁提高性能
             * - 与显示方法形成配对操作
             * - 保持界面整洁用户体验
             * - 避免内存泄漏确保稳定
             * 
             * 应用场景：
             * - 鼠标离开冒险者元素时
             * - 点击其他界面元素时
             * - 界面状态切换时
             * - 避免信息遮挡时
             */
            hideTooltip() {
                document.getElementById('tooltip').style.display = 'none';
            }

            /**
             * 显示通知消息 - UI反馈系统
             * 在屏幕顶部显示临时通知消息，提供操作反馈
             * 支持不同类型的通知样式，增强用户体验
             * 实现自动消失和样式区分功能
             * 
             * 通知类型：
             * 1. success - 成功消息（绿色背景）
             * 2. error - 错误消息（红色背景）
             * 3. info - 信息消息（默认蓝色背景）
             * 
             * 显示机制：
             * 1. 显示3秒后自动消失
             * 2. 支持消息覆盖（新消息替换旧消息）
             * 3. 根据类型应用不同颜色样式
             * 4. 顶部固定位置显示确保可见性
             * 
             * 样式设计：
             * - 成功消息：绿色背景rgba(46, 204, 113, 0.9)
             * - 错误消息：红色背景rgba(231, 76, 60, 0.9)
             * - 信息消息：默认使用成功消息样式
             * - 半透明设计避免完全遮挡界面
             * 
             * 时间控制机制：
             * - 显示时长：3000毫秒（3秒）
             * - 使用setTimeout实现延迟隐藏
             * - 新消息立即显示覆盖旧消息
             * - 避免消息堆积确保清晰
             * 
             * DOM操作安全：
             * - 获取元素后检查存在性
             * - 文本内容安全设置
             * - 样式属性直接控制
             * - 避免复杂DOM操作提高性能
             * 
             * @param {string} message - 要显示的通知消息
             * @param {string} type - 通知类型（success/error，默认为success）
             */
            showNotification(message, type = 'success') {
                const notification = document.getElementById('notification');
                notification.textContent = message;
                notification.style.background = type === 'success' ? 'rgba(46, 204, 113, 0.9)' : 'rgba(231, 76, 60, 0.9)';
                notification.style.display = 'block';

                setTimeout(() => {
                    notification.style.display = 'none';
                }, 3000);
            }

            /**
             * 显示资源变化通知 - 游戏反馈系统
             * 在屏幕特定位置显示资源变化的临时通知
             * 专门用于显示金币等资源的增减变化
             * 
             * 显示特点：
             * 1. 显示位置在屏幕特定区域（资源通知区域）
             * 2. 显示时间较短（2秒）
             * 3. 专门显示金币变化信息
             * 4. 只在有实际变化时显示（gold != 0）
             * 
             * @param {number} gold - 金币变化数量（正数表示增加，负数表示减少）
             */
            showResourceNotification(gold = 0) {
                if (gold === 0) return;

                const notification = document.getElementById('resource-notification');
                notification.textContent = `金币 +${gold}`;
                notification.style.display = 'block';

                setTimeout(() => {
                    notification.style.display = 'none';
                }, 2000);
            }

            // 显示怪物详情模态框
            showMonsterModal(monster) {
                this.selectedMonster = monster;
                
                // 设置模态框标题
                document.getElementById('monster-modal-title').innerHTML = `<i class="fas fa-dragon"></i> ${monster.attribute}${monster.rank}${monster.type} 的详情`;
                const modalContent = document.getElementById('monster-modal-content');
                
                // 获取怪物属性颜色
                const attributeColor = Config.MONSTER_ATTRIBUTES[monster.attribute].color;
                
                // 生成怪物基本信息
                let basicInfoHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-info-circle"></i> 基本信息</div>
                        <div class="stats-grid">
                            <div class="stat-item">
                                <span>类型</span>
                                <span style="color: ${attributeColor}">${monster.type}</span>
                            </div>
                            <div class="stat-item">
                                <span>稀有度</span>
                                <span class="rarity-${monster.rank.toLowerCase()}">${monster.rank}</span>
                            </div>
                            <div class="stat-item">
                                <span>属性</span>
                                <span style="color: ${attributeColor}">${monster.attribute}</span>
                            </div>
                            <div class="stat-item">
                                <span>行为</span>
                                <span>${monster.behavior}</span>
                            </div>
                            <div class="stat-item">
                                <span>等级</span>
                                <span>Lv.${monster.level}</span>
                            </div>
                            <div class="stat-item">
                                <span>生命值</span>
                                <span>${Math.floor(monster.hp)}/${monster.maxHp}</span>
                            </div>
                            <div class="stat-item">
                                <span>攻击力</span>
                                <span>${monster.attack}</span>
                            </div>
                            <div class="stat-item">
                                <span>防御力</span>
                                <span>${monster.defense}</span>
                            </div>
                            <div class="stat-item">
                                <span>移动速度</span>
                                <span>${monster.speed.toFixed(1)}</span>
                            </div>
                            <div class="stat-item">
                                <span>警戒范围</span>
                                <span>${monster.aggroRadius}</span>
                            </div>
                            <div class="stat-item">
                                <span>奖励金币</span>
                                <span>${monster.rewardGold}</span>
                            </div>
                            <div class="stat-item">
                                <span>奖励经验</span>
                                <span>${monster.rewardExp}</span>
                            </div>
                            <div class="stat-item">
                                <span>掉落率</span>
                                <span>${(monster.dropRate * 100).toFixed(1)}%</span>
                            </div>
                            <div class="stat-item">
                                <span>位置</span>
                                <span>(${Math.floor(monster.x)}, ${Math.floor(monster.y)})</span>
                            </div>
                        </div>
                    </div>
                `;
                
                // 技能信息
                let skillsHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-magic"></i> 怪物技能</div>
                        <div>
                `;
                
                if (monster.skills && monster.skills.length > 0) {
                    monster.skills.forEach(skill => {
                        skillsHtml += `<div class="log-entry" style="border-left-color: ${attributeColor}">${skill}</div>`;
                    });
                } else {
                    skillsHtml += '<div class="log-entry">普通攻击</div>';
                }
                
                skillsHtml += '</div></div>';
                
                // 掉落信息
                let dropInfoHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-gift"></i> 可能掉落</div>
                        <div>
                            <div class="log-entry">装备等级: Lv.${monster.equipmentDropLevel}</div>
                            <div class="log-entry">装备稀有度: ${Config.EQUIPMENT_RARITIES[monster.equipmentDropRarity] || '白色'}</div>
                            <div class="log-entry">掉落率: ${(monster.dropRate * 100).toFixed(1)}%</div>
                        </div>
                    </div>
                `;
                
                modalContent.innerHTML = basicInfoHtml + skillsHtml + dropInfoHtml;
                
                // 显示模态框
                document.getElementById('monster-modal').style.display = 'block';
            }
            
            // 隐藏怪物模态框
            hideMonsterModal() {
                document.getElementById('monster-modal').style.display = 'none';
                this.selectedMonster = null;
            }
            
            /**
             * 显示建筑详情模态框 - 建筑系统
             * 展示指定建筑的详细信息和操作选项
             * 提供升级、拆除等功能
             * 显示建筑的收入和效果信息
             * 
             * 显示内容：
             * 1. 建筑基本信息（名称、类型、等级）
             * 2. 建筑属性（收入、效果等）
             * 3. 建筑位置信息
             * 4. 升级信息（下一级效果、升级成本）
             * 5. 操作按钮（升级、拆除等）
             * 
             * 功能特点：
             * - 实时显示建筑等级和收入
             * - 支持建筑升级操作
             * - 显示升级所需资源
             * - 提供拆除建筑选项
             * - 支持建筑效果说明
             * 
             * 数据来源：
             * - 建筑对象属性
             * - Config.BUILDINGS配置
             * - 游戏当前状态
             * 
             * @param {Object} building - 建筑对象
             */
            showBuildingModal(building) {
                this.selectedBuilding = building;
                
                // 设置模态框标题
                const buildingConfig = Config.BUILDINGS[building.type];
                const iconClass = buildingConfig ? buildingConfig.icon : 'fas fa-building';
                document.getElementById('modal-title').innerHTML = `<i class="${iconClass}"></i> ${building.type} 的详情`;
                const modalContent = document.getElementById('modal-content');
                
                // 计算实际收入（考虑称号加成）
                const baseIncome = building.level * (building.income || 10);
                const actualIncome = Math.floor(baseIncome * (1 + (this.titleEffects.buildingIncome || 0)));
                
                // 生成建筑基本信息
                let basicInfoHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-info-circle"></i> 基本信息</div>
                        <div class="stats-grid">
                            <div class="stat-item">
                                <span>类型</span>
                                <span>${building.type}</span>
                            </div>
                            <div class="stat-item">
                                <span>等级</span>
                                <span>Lv.${building.level}</span>
                            </div>
                            <div class="stat-item">
                                <span>基础收入</span>
                                <span>${building.income || 10}金/10秒</span>
                            </div>
                            <div class="stat-item">
                                <span>实际收入</span>
                                <span>${actualIncome}金/10秒</span>
                            </div>
                            ${this.titleEffects.buildingIncome ? `
                            <div class="stat-item">
                                <span>称号加成</span>
                                <span>+${Math.floor(baseIncome * this.titleEffects.buildingIncome)}金/10秒</span>
                            </div>
                            ` : ''}
                            <div class="stat-item">
                                <span>位置</span>
                                <span>(${Math.floor(building.x)}, ${Math.floor(building.y)})</span>
                            </div>
                            <div class="stat-item">
                                <span>交互次数</span>
                                <span>${building.interactionCount || 0}</span>
                            </div>
                            <div class="stat-item">
                                <span>交互收入</span>
                                <span>${building.interactionIncome || 0}金</span>
                            </div>
                        </div>
                    </div>
                `;
                
                // 建筑效果信息
                let effectsHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-star"></i> 建筑效果</div>
                        <div>
                `;
                
                if (buildingConfig && buildingConfig.effects) {
                    for (const effect in buildingConfig.effects) {
                        effectsHtml += `<div class="log-entry">${effect}: ${buildingConfig.effects[effect]}</div>`;
                    }
                } else {
                    effectsHtml += '<div class="log-entry">无特殊效果</div>';
                }
                
                effectsHtml += '</div></div>';
                
                // 升级信息
                const nextLevel = building.level + 1;
                const upgradeCostGold = Math.floor((buildingConfig ? buildingConfig.cost : 100) * Math.pow(1.5, building.level));
                const upgradeCostCharm = Math.floor((buildingConfig ? buildingConfig.charmCost || 0 : 0) * Math.pow(1.3, building.level));
                
                let upgradeHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-arrow-up"></i> 升级信息 (Lv.${nextLevel})</div>
                        <div class="stats-grid">
                            <div class="stat-item">
                                <span>升级费用</span>
                                <span>${upgradeCostGold}金</span>
                            </div>
                `;
                
                if (upgradeCostCharm > 0) {
                    upgradeHtml += `
                        <div class="stat-item">
                            <span>魅力消耗</span>
                            <span>${upgradeCostCharm}</span>
                        </div>
                    `;
                }
                
                // 计算升级后的实际收入（考虑称号加成）
                const nextBaseIncome = nextLevel * (building.income || 10);
                const nextActualIncome = Math.floor(nextBaseIncome * (1 + (this.titleEffects.buildingIncome || 0)));
                
                upgradeHtml += `
                            <div class="stat-item">
                                <span>升级后收入</span>
                                <span>${nextActualIncome}金/10秒</span>
                            </div>
                        </div>
                    </div>
                `;
                
                // 操作按钮
                let actionsHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-cogs"></i> 操作</div>
                        <div class="button-group">
                `;
                
                // 升级按钮
                if (this.gold >= upgradeCostGold && (!upgradeCostCharm || this.charm >= upgradeCostCharm)) {
                    actionsHtml += `<button class="btn-primary" onclick="game.upgradeBuilding(${this.buildings.indexOf(building)})">升级建筑</button>`;
                } else {
                    actionsHtml += `<button class="btn-disabled" disabled>金币或魅力不足</button>`;
                }
                
                // 拆除按钮
                actionsHtml += `<button class="btn-danger" onclick="game.demolishBuilding(${this.buildings.indexOf(building)})">拆除建筑</button>`;
                
                actionsHtml += '</div></div>';
                
                modalContent.innerHTML = basicInfoHtml + effectsHtml + upgradeHtml + actionsHtml;
                
                // 显示模态框
                document.getElementById('modal').style.display = 'block';
            }
            
            /**
             * 升级建筑 - 建筑系统
             * 提升指定建筑的等级
             * 扣除升级所需资源
             * 更新建筑属性和收入
             * 显示升级通知
             * 
             * 升级机制：
             * 1. 检查资源是否充足
             * 2. 扣除升级费用
             * 3. 提升建筑等级
             * 4. 更新建筑收入
             * 5. 显示升级效果
             * 
             * 费用计算：
             * - 金币成本 = 基础费用 × 1.5^等级
             * - 魅力成本 = 基础费用 × 1.3^等级
             * - 成本随等级指数增长
             * 
             * 效果更新：
             * - 收入按等级线性增长
             * - 特殊效果可能随等级变化
             * - 建筑外观可能变化
             * 
             * @param {number} buildingIndex - 建筑在数组中的索引
             */
            upgradeBuilding(buildingIndex) {
                if (buildingIndex < 0 || buildingIndex >= this.buildings.length) return;
                
                const building = this.buildings[buildingIndex];
                const buildingConfig = Config.BUILDINGS[building.type];
                const nextLevel = building.level + 1;
                // 修复：使用Config.BUILDING_COSTS而不是Config.BUILDINGS来获取基础成本
                const baseCost = Config.BUILDING_COSTS[building.type] || { gold: 100, charm: 0 };
                const upgradeCostGold = Math.floor(baseCost.gold * 0.5 * Math.pow(1.4, building.level));
                const upgradeCostCharm = Math.floor((baseCost.charm || 0) * 0.5 * Math.pow(1.4, building.level));
                
                // 检查资源是否充足
                if (this.gold >= upgradeCostGold && this.charm >= upgradeCostCharm) {
                    // 扣除费用
                    this.gold -= upgradeCostGold;
                    this.charm -= upgradeCostCharm;
                    
                    // 升级建筑
                    building.level = nextLevel;
                    
                    // 显示通知
                    this.showNotification(`${building.type} 升级到 Lv.${nextLevel}！`, 'success');
                    
                    // 关闭模态框
                    document.getElementById('modal').style.display = 'none';
                    
                    // 更新UI
                    this.updateUI();
                } else {
                    this.showNotification('资源不足，无法升级建筑！', 'error');
                }
            }
            
            /**
             * 拆除建筑 - 建筑系统
             * 移除指定建筑
             * 返还部分资源
             * 更新游戏状态
             * 显示拆除通知
             * 
             * 拆除机制：
             * 1. 确认拆除操作
             * 2. 返还部分建造费用
             * 3. 从建筑列表中移除
             * 4. 更新游戏状态
             * 5. 显示拆除效果
             * 
             * 资源返还：
             * - 返还50%的建造费用
             * - 金币和魅力分别返还
             * - 返还资源可用于重建
             * 
             * 状态更新：
             * - 建筑数量减少
             * - 总收入可能减少
             * - 建筑效果消失
             * 
             * @param {number} buildingIndex - 建筑在数组中的索引
             */
            demolishBuilding(buildingIndex) {
                if (buildingIndex < 0 || buildingIndex >= this.buildings.length) return;
                
                const building = this.buildings[buildingIndex];
                // 修复：使用Config.BUILDING_COSTS而不是Config.BUILDINGS来获取基础成本
                const baseCost = Config.BUILDING_COSTS[building.type] || { gold: 100, charm: 0 };
                const refundGold = Math.floor(baseCost.gold * 0.5 * Math.pow(1.4, building.level - 1) * 0.5);
                const refundCharm = Math.floor((baseCost.charm || 0) * 0.5 * Math.pow(1.4, building.level - 1) * 0.5);
                
                // 确认拆除操作
                if (confirm(`确定要拆除 ${building.type} 吗？将返还 ${refundGold} 金币和 ${refundCharm} 魅力值。`)) {
                    // 返还资源
                    this.gold += refundGold;
                    this.charm += refundCharm;
                    
                    // 从建筑列表中移除
                    this.buildings.splice(buildingIndex, 1);
                    
                    // 显示通知
                    this.showNotification(`${building.type} 已拆除，获得 ${refundGold} 金币和 ${refundCharm} 魅力值！`, 'success');
                    
                    // 关闭模态框
                    document.getElementById('modal').style.display = 'none';
                    
                    // 更新UI
                    this.updateUI();
                }
            }

            showAdventurerModal(adventurer) {
                this.selectedAdventurer = adventurer;

                document.getElementById('modal-title').innerHTML = `<i class="fas fa-user"></i> ${adventurer.name}的详细信息`;
                const modalContent = document.getElementById('modal-content');

                // 基本信息
                let basicInfoHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-info-circle"></i> 基本信息</div>
                        <div class="stats-grid">
                            <div class="stat-item">
                                <span>职业</span>
                                <span>${adventurer.class}</span>
                            </div>
                            <div class="stat-item">
                                <span>等级</span>
                                <span>Lv.${adventurer.level}</span>
                            </div>
                            <div class="stat-item">
                                <span>经验值</span>
                                <span>${adventurer.exp}/${adventurer.maxExp}</span>
                            </div>
                            <div class="stat-item">
                                <span>生命值</span>
                                <span>${Math.floor(adventurer.hp)}/${adventurer.maxHp}</span>
                            </div>
                            <div class="stat-item">
                                <span>魔法值</span>
                                <span>${Math.floor(adventurer.mp)}/${adventurer.maxMp}</span>
                            </div>
                            <div class="stat-item">
                                <span>饥饿值</span>
                                <span>${Math.floor(adventurer.hunger)}/${adventurer.maxHunger}</span>
                            </div>
                            <div class="stat-item">
                                <span>攻击力</span>
                                <span>${adventurer.attack}</span>
                            </div>
                            <div class="stat-item">
                                <span>防御力</span>
                                <span>${adventurer.defense}</span>
                            </div>
                            <div class="stat-item">
                                <span>速度</span>
                                <span>${adventurer.speed}</span>
                            </div>
                            <div class="stat-item">
                                <span>暴击率</span>
                                <span>${(adventurer.critRate * 100).toFixed(1)}%</span>
                            </div>
                            <div class="stat-item">
                                <span>暴击伤害</span>
                                <span>${(adventurer.critDamage * 100).toFixed(0)}%</span>
                            </div>
                            <div class="stat-item">
                                <span>金币</span>
                                <span>${adventurer.gold}</span>
                            </div>
                            <div class="stat-item">
                                <span>状态</span>
                                <span>${adventurer.state}</span>
                            </div>
                            <div class="stat-item">
                                <span>位置</span>
                                <span>(${Math.floor(adventurer.x)}, ${Math.floor(adventurer.y)})</span>
                            </div>
                            <div class="stat-item">
                                <span>副本最高层数</span>
                                <span>${adventurer.highestDungeonFloor || 0}</span>
                            </div>
                        </div>
                    </div>
                `;

                // 技能信息
                let skillsHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-magic"></i> 技能</div>
                        <div>
                `;

                adventurer.skills.forEach(skill => {
                    skillsHtml += `<div class="log-entry">${skill}</div>`;
                });

                if (adventurer.skills.length === 0) {
                    skillsHtml += '<div class="log-entry">暂无技能</div>';
                }

                skillsHtml += '</div></div>';

                // 装备信息
                let equipmentHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-tshirt"></i> 装备栏</div>
                        <div class="equipment-grid">
                `;

                // 获取当前装备的套装信息
                const setCounts = {};
                for (const slot in adventurer.equipment) {
                    const item = adventurer.equipment[slot];
                    if (item && item.set) {
                        const setName = item.set.replace('套装：', '');
                        setCounts[setName] = (setCounts[setName] || 0) + 1;
                    }
                }

                for (const slot in adventurer.equipment) {
                    const item = adventurer.equipment[slot];
                    if (item) {
                        const rarityClass = this.getRarityClass(item.rarity);
                        const durabilityPercent = (item.durability / item.maxDurability) * 100;
                        let durabilityClass = 'equipment-durability-fill';
                        if (durabilityPercent < 30) {
                            durabilityClass += ' equipment-durability-low';
                        } else if (durabilityPercent < 60) {
                            durabilityClass += ' equipment-durability-medium';
                        }
                        
                        // 获取装备图标
                        let iconClass = 'fas fa-tshirt';
                        if (slot === '武器') iconClass = 'fas fa-sword';
                        else if (slot === '头盔') iconClass = 'fas fa-helmet-battle';
                        else if (slot === '胸甲') iconClass = 'fas fa-vest';
                        else if (slot === '护手') iconClass = 'fas fa-hand-paper';
                        else if (slot === '护腿') iconClass = 'fas fa-socks';
                        else if (slot === '靴子') iconClass = 'fas fa-shoe-prints';
                        else if (slot === '项链') iconClass = 'fas fa-gem';
                        else if (slot === '戒指') iconClass = 'fas fa-ring';
                        else if (slot === '腰带') iconClass = 'fas fa-belt';
                        else if (slot === '护符') iconClass = 'fas fa-amulet';
                        
                        equipmentHtml += `
                            <div class="equipment-slot" data-item-id="${item.id}" data-slot="${slot}">
                                <div class="equipment-icon ${rarityClass}">
                                    <i class="${iconClass}"></i>
                                </div>
                                <div class="equipment-name ${rarityClass}">${item.name}</div>
                                <div class="equipment-stats">Lv.${item.level}</div>
                                ${item.set ? '<div class="equipment-set-indicator" title="' + item.set + '"></div>' : ''}
                                <div class="equipment-durability-bar">
                                    <div class="${durabilityClass}" style="width: ${durabilityPercent}%"></div>
                                </div>
                            </div>
                        `;
                    } else {
                        // 获取空装备槽图标
                        let iconClass = 'fas fa-tshirt';
                        if (slot === '武器') iconClass = 'fas fa-sword';
                        else if (slot === '头盔') iconClass = 'fas fa-helmet-battle';
                        else if (slot === '胸甲') iconClass = 'fas fa-vest';
                        else if (slot === '护手') iconClass = 'fas fa-hand-paper';
                        else if (slot === '护腿') iconClass = 'fas fa-socks';
                        else if (slot === '靴子') iconClass = 'fas fa-shoe-prints';
                        else if (slot === '项链') iconClass = 'fas fa-gem';
                        else if (slot === '戒指') iconClass = 'fas fa-ring';
                        else if (slot === '腰带') iconClass = 'fas fa-belt';
                        else if (slot === '护符') iconClass = 'fas fa-amulet';
                        
                        equipmentHtml += `
                            <div class="equipment-slot">
                                <div class="equipment-icon" style="color: #7f8c8d;">
                                    <i class="${iconClass}"></i>
                                </div>
                                <div class="equipment-name" style="color: #7f8c8d;">空</div>
                                <div class="equipment-stats" style="color: #95a5a6;">${slot}</div>
                            </div>
                        `;
                    }
                }

                // 显示套装效果
                let setBonusHtml = '';
                for (const setName in setCounts) {
                    const setConfig = Config.EQUIPMENT_SETS[setName];
                    if (setConfig) {
                        const pieces = setCounts[setName];
                        const requiredPieces = setConfig.pieces;
                        setBonusHtml += `
                            <div class="set-bonus-info">
                                <div class="set-name">${setName}套装 (${pieces}/${requiredPieces})</div>
                                ${pieces >= requiredPieces ? 
                                    `<div class="set-bonus-active">激活效果: ${Object.entries(setConfig.bonus).map(([key, value]) => {
                                        const statNames = {
                                            'attack': '攻击',
                                            'defense': '防御',
                                            'hp': '生命',
                                            'mp': '魔法',
                                            'speed': '速度',
                                            'critRate': '暴击率',
                                            'critDamage': '暴击伤害',
                                            'allStats': '全属性'
                                        };
                                        const statName = statNames[key] || key;
                                        const displayValue = key === 'critRate' ? `${(value * 100).toFixed(1)}%` : 
                                                         key === 'critDamage' ? `${(value * 100).toFixed(0)}%` : 
                                                         key === 'allStats' ? `${(value * 100).toFixed(0)}%` : value;
                                        return `${statName}+${displayValue}`;
                                    }).join(', ')}</div>` : 
                                    `<div class="set-bonus-inactive">还需${requiredPieces - pieces}件激活套装效果</div>`
                                }
                            </div>
                        `;
                    }
                }
                
                if (setBonusHtml) {
                    equipmentHtml += `
                        <div class="set-bonus-container">
                            <div class="modal-section-title"><i class="fas fa-crown"></i> 套装效果</div>
                            ${setBonusHtml}
                        </div>
                    `;
                }

                equipmentHtml += `</div></div>`;

                // 背包信息
                let inventoryHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-backpack"></i> 背包 (${adventurer.inventory.length}/20)</div>
                        <div class="inventory-grid">
                `;

                if (adventurer.inventory.length === 0) {
                    inventoryHtml += `<div>背包空空如也</div>`;
                } else {
                    adventurer.inventory.slice(0, 9).forEach(item => {
                        const rarityClass = this.getRarityClass(item.rarity);
                        // 获取装备图标
                        let iconClass = 'fas fa-tshirt';
                        if (item.slot === '武器') iconClass = 'fas fa-sword';
                        else if (item.slot === '头盔') iconClass = 'fas fa-helmet-battle';
                        else if (item.slot === '胸甲') iconClass = 'fas fa-vest';
                        else if (item.slot === '护手') iconClass = 'fas fa-hand-paper';
                        else if (item.slot === '护腿') iconClass = 'fas fa-socks';
                        else if (item.slot === '靴子') iconClass = 'fas fa-shoe-prints';
                        else if (item.slot === '项链') iconClass = 'fas fa-gem';
                        else if (item.slot === '戒指') iconClass = 'fas fa-ring';
                        else if (item.slot === '腰带') iconClass = 'fas fa-belt';
                        else if (item.slot === '护符') iconClass = 'fas fa-amulet';
                        
                        inventoryHtml += `
                            <div class="inventory-item ${rarityClass}" data-item-id="${item.id}">
                                <div class="inventory-item-icon">
                                    <i class="${iconClass}"></i>
                                </div>
                                <div class="inventory-item-name">${item.name}</div>
                                <div class="inventory-item-level">Lv.${item.level}</div>
                                ${item.set ? '<div class="inventory-item-set" title="' + item.set + '"></div>' : ''}
                            </div>
                        `;
                    });

                    if (adventurer.inventory.length > 9) {
                        inventoryHtml += `<div>...还有${adventurer.inventory.length - 9}件物品</div>`;
                    }
                }

                inventoryHtml += `</div></div>`;

                // 行动日志
                let logHtml = `
                    <div class="modal-section">
                        <div class="modal-section-title"><i class="fas fa-scroll"></i> 行动日志</div>
                        <div class="log-container">
                `;

                // 倒序显示最新的10条日志
                const recentLogs = adventurer.log.slice(-10);
                for (let i = recentLogs.length - 1; i >= 0; i--) {
                    logHtml += `<div class="log-entry">${recentLogs[i]}</div>`;
                }

                if (adventurer.log.length === 0) {
                    logHtml += `<div class="log-entry">暂无日志</div>`;
                }

                logHtml += `</div></div>`;

                modalContent.innerHTML = basicInfoHtml + skillsHtml + equipmentHtml + inventoryHtml + logHtml;

                // 添加装备点击事件
                modalContent.querySelectorAll('.equipment-slot').forEach(slot => {
                    const itemId = slot.getAttribute('data-item-id');
                    if (itemId) {
                        const equipment = adventurer.equipment[slot.getAttribute('data-slot')];
                        slot.addEventListener('click', () => {
                            this.showEquipmentModal(equipment, adventurer);
                        });
                    }
                });

                // 添加物品提示和点击事件
                modalContent.querySelectorAll('.inventory-item').forEach(item => {
                    const itemId = item.getAttribute('data-item-id');
                    const equipment = adventurer.inventory.find(i => i.id == itemId);

                    item.addEventListener('mouseover', (e) => {
                        const tooltip = document.getElementById('tooltip');
                        const rarityClass = this.getRarityClass(equipment.rarity);

                        // 获取装备图标
                        let iconClass = 'fas fa-tshirt';
                        if (equipment.slot === '武器') iconClass = 'fas fa-sword';
                        else if (equipment.slot === '头盔') iconClass = 'fas fa-helmet-battle';
                        else if (equipment.slot === '胸甲') iconClass = 'fas fa-vest';
                        else if (equipment.slot === '护手') iconClass = 'fas fa-hand-paper';
                        else if (equipment.slot === '护腿') iconClass = 'fas fa-socks';
                        else if (equipment.slot === '靴子') iconClass = 'fas fa-shoe-prints';
                        else if (equipment.slot === '项链') iconClass = 'fas fa-gem';
                        else if (equipment.slot === '戒指') iconClass = 'fas fa-ring';
                        else if (equipment.slot === '腰带') iconClass = 'fas fa-belt';
                        else if (equipment.slot === '护符') iconClass = 'fas fa-amulet';

                        tooltip.innerHTML = `
                            <div class="tooltip-header">
                                <div class="tooltip-icon ${rarityClass}">
                                    <i class="${iconClass}"></i>
                                </div>
                                <div class="tooltip-name ${rarityClass}">${equipment.name}</div>
                            </div>
                            <div class="tooltip-stats">
                                <div>部位: ${equipment.slot}</div>
                                <div>稀有度: <span class="${rarityClass}">${equipment.rarity}</span></div>
                                <div>等级: ${equipment.level}</div>
                                ${equipment.attack > 0 ? `<div>攻击: +${equipment.attack}</div>` : ''}
                                ${equipment.defense > 0 ? `<div>防御: +${equipment.defense}</div>` : ''}
                                ${equipment.hp > 0 ? `<div>生命: +${equipment.hp}</div>` : ''}
                                ${equipment.mp > 0 ? `<div>魔法: +${equipment.mp}</div>` : ''}
                                ${equipment.speed > 0 ? `<div>速度: +${equipment.speed}</div>` : ''}
                                ${equipment.critRate > 0 ? `<div>暴击率: +${(equipment.critRate * 100).toFixed(1)}%</div>` : ''}
                                ${equipment.critDamage > 0 ? `<div>暴击伤害: +${(equipment.critDamage * 100).toFixed(0)}%</div>` : ''}
                                ${equipment.special ? `<div class="tooltip-special">${equipment.special}</div>` : ''}
                                ${equipment.set ? `<div class="tooltip-set">${equipment.set}</div>` : ''}
                                ${equipment.bonus ? `<div class="tooltip-bonus">${equipment.bonus}</div>` : ''}
                                <div>耐久度: ${equipment.durability}/${equipment.maxDurability}</div>
                                <div>价值: ${equipment.value}金</div>
                            </div>
                        `;
                        tooltip.style.display = 'block';
                    });

                    item.addEventListener('mouseout', () => {
                        this.hideTooltip();
                    });

                    item.addEventListener('click', () => {
                        this.showEquipmentModal(equipment, adventurer);
                    });
                });

                document.getElementById('modal').style.display = 'block';
            }

            /**
             * 显示装备详情模态框 - 装备系统
             * 展示指定装备的详细信息和操作选项
             * 根据装备位置显示不同的操作按钮
             * 提供装备、卸下、出售、修理等功能
             * 
             * 显示内容：
             * 1. 装备基本信息（名称、部位、稀有度、等级）
             * 2. 装备属性加成（攻击、防御、生命、魔法等）
             * 3. 特殊效果和套装属性
             * 4. 耐久度和价值信息
             * 5. 操作按钮（装备/卸下、出售、修理）
             * 
             * 操作按钮：
             * - 装备状态：显示"装备"和"出售"按钮
             * - 已装备状态：显示"卸下"按钮
             * - 损坏状态：显示"修理"按钮
             * - 按钮绑定对应处理方法
             * 
             * 稀有度显示：
             * - 根据装备稀有度应用不同CSS类
             * - 彩虹色显示最高稀有度装备
             * - 支持所有稀有度等级显示
             * 
             * 数据展示：
             * - 只显示大于0的属性值
             * - 数值格式化显示（百分比、整数）
             * - 耐久度显示当前/最大值
             * - 出售价格显示半价
             * - 修理费用动态计算
             * 
             * 界面控制：
             * - 设置选中装备引用
             * - 更新模态框标题和内容
             * - 显示模态框元素
             * - 保持界面一致性
             * 
             * @param {Object} equipment - 要显示的装备对象
             * @param {Object} adventurer - 装备所属的冒险者对象
             */
            showEquipmentModal(equipment, adventurer) {
                this.selectedEquipment = equipment;

                const rarityClass = this.getRarityClass(equipment.rarity);

                document.getElementById('equipment-modal-title').innerHTML = `<i class="fas fa-tshirt"></i> <span class="${rarityClass}">${equipment.name}</span>`;
                const modalContent = document.getElementById('equipment-modal-content');

                // 获取装备图标
                let iconClass = 'fas fa-tshirt';
                if (equipment.slot === '武器') iconClass = 'fas fa-sword';
                else if (equipment.slot === '头盔') iconClass = 'fas fa-helmet-battle';
                else if (equipment.slot === '胸甲') iconClass = 'fas fa-vest';
                else if (equipment.slot === '护手') iconClass = 'fas fa-hand-paper';
                else if (equipment.slot === '护腿') iconClass = 'fas fa-socks';
                else if (equipment.slot === '靴子') iconClass = 'fas fa-shoe-prints';
                else if (equipment.slot === '项链') iconClass = 'fas fa-gem';
                else if (equipment.slot === '戒指') iconClass = 'fas fa-ring';
                else if (equipment.slot === '腰带') iconClass = 'fas fa-belt';
                else if (equipment.slot === '护符') iconClass = 'fas fa-amulet';

                let html = `
                    <div class="equipment-details">
                        <div class="equipment-detail-row">
                            <span>名称</span>
                            <span class="${rarityClass}"><i class="${iconClass}"></i> ${equipment.name}</span>
                        </div>
                        <div class="equipment-detail-row">
                            <span>部位</span>
                            <span>${equipment.slot}</span>
                        </div>
                        <div class="equipment-detail-row">
                            <span>稀有度</span>
                            <span class="${rarityClass}">${equipment.rarity}</span>
                        </div>
                        <div class="equipment-detail-row">
                            <span>等级</span>
                            <span>${equipment.level}</span>
                        </div>
                `;

                if (equipment.attack > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>攻击</span>
                            <span>+${equipment.attack}</span>
                        </div>
                    `;
                }
                if (equipment.defense > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>防御</span>
                            <span>+${equipment.defense}</span>
                        </div>
                    `;
                }
                if (equipment.hp > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>生命</span>
                            <span>+${equipment.hp}</span>
                        </div>
                    `;
                }
                if (equipment.mp > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>魔法</span>
                            <span>+${equipment.mp}</span>
                        </div>
                    `;
                }
                if (equipment.speed > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>速度</span>
                            <span>+${equipment.speed}</span>
                        </div>
                    `;
                }
                if (equipment.critRate > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>暴击率</span>
                            <span>+${(equipment.critRate * 100).toFixed(1)}%</span>
                        </div>
                    `;
                }
                if (equipment.critDamage > 0) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>暴击伤害</span>
                            <span>+${(equipment.critDamage * 100).toFixed(0)}%</span>
                        </div>
                    `;
                }
                if (equipment.special) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>特殊效果</span>
                            <span>${equipment.special}</span>
                        </div>
                    `;
                }
                if (equipment.set) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>套装属性</span>
                            <span>${equipment.set}</span>
                        </div>
                    `;
                }
                if (equipment.bonus) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>额外属性</span>
                            <span>${equipment.bonus}</span>
                        </div>
                    `;
                }
                // 显示世界装标记
                if (equipment.isWorldDrop) {
                    html += `
                        <div class="equipment-detail-row">
                            <span>特殊标记</span>
                            <span class="rarity-rainbow">世界装</span>
                        </div>
                    `;
                }
                html += `
                        <div class="equipment-detail-row">
                            <span>耐久度</span>
                            <span>${equipment.durability}/${equipment.maxDurability}</span>
                        </div>
                        <div class="equipment-detail-row">
                            <span>价值</span>
                            <span>${equipment.value}金</span>
                        </div>
                    </div>

                    <div class="equipment-action-buttons">
                `;

                const inInventory = adventurer.inventory.some(item => item.id === equipment.id);

                if (inInventory) {
                    html += `
                        <button onclick="game.equipItem(game.selectedEquipment, game.selectedAdventurer)">
                            <i class="fas fa-user"></i> 装备
                        </button>
                        <button onclick="game.sellItem(game.selectedEquipment, game.selectedAdventurer)">
                            <i class="fas fa-coins"></i> 出售 (${Math.max(1, Math.floor(Math.floor(equipment.value * 0.5) * (1 - game.selectedAdventurer.gold * 0.00005)))}金)
                        </button>
                    `;
                } else {
                    html += `
                        <button onclick="game.unequipItem(game.selectedEquipment, game.selectedAdventurer)">
                            <i class="fas fa-user-slash"></i> 卸下
                        </button>
                    `;
                }

                if (equipment.durability < equipment.maxDurability) {
                    // 动态定价：修理费用基于装备价值和冒险者总金钱
                    const baseRepairCost = Math.floor(equipment.value * 0.2 * (1 - equipment.durability / equipment.maxDurability));
                    const repairCost = Math.max(1, Math.floor(baseRepairCost * (1 + game.selectedAdventurer.gold * 0.0001)));
                    html += `
                        <button onclick="game.repairItem(game.selectedEquipment, game.selectedAdventurer)">
                            <i class="fas fa-tools"></i> 修理 (${repairCost}金)
                        </button>
                    `;
                }

                html += `</div>`;

                modalContent.innerHTML = html;
                document.getElementById('equipment-modal').style.display = 'block';
            }

            /**
             * 装备物品 - 装备系统
             * 将指定装备装备到冒险者的对应部位
             * 处理装备替换和背包更新
             * 更新装备属性加成并提供反馈
             * 
             * 装备流程：
             * 1. 检查目标部位是否已有装备
             * 2. 如有装备则放回背包
             * 3. 将新装备放到对应部位
             * 4. 从背包中移除装备
             * 5. 记录装备操作日志
             * 6. 显示装备成功通知
             * 7. 更新装备属性加成
             * 8. 关闭装备模态框
             * 9. 重新显示冒险者详情
             * 
             * 装备替换：
             * - 自动将原装备放回背包
             * - 保持装备ID唯一性
             * - 避免装备丢失
             * - 支持所有装备部位
             * 
             * 数据更新：
             * - 装备部位对象更新
             * - 背包物品列表过滤
             * - 装备属性加成重新计算
             * - 冒险者日志记录添加
             * 
             * 用户反馈：
             * - 操作通知显示装备名称
             * - 冒险者日志记录时间戳
             * - 界面自动刷新显示
             * - 模态框状态管理
             * 
             * @param {Object} equipment - 要装备的装备对象
             * @param {Object} adventurer - 要装备的冒险者对象
             */
            equipItem(equipment, adventurer) {
                const slot = equipment.slot;
                const currentEquip = adventurer.equipment[slot];

                if (currentEquip) {
                    adventurer.inventory.push(currentEquip);
                }

                adventurer.equipment[slot] = equipment;
                adventurer.inventory = adventurer.inventory.filter(i => i.id !== equipment.id);

                adventurer.log.push(`${new Date().toLocaleTimeString()} 装备了${equipment.name}`);
                this.showNotification(`${adventurer.name}装备了${equipment.name}`);

                this.updateEquipmentBonuses(adventurer);

                this.hideEquipmentModal();
                this.showAdventurerModal(adventurer);
            }

            /**
             * 卸下装备 - 装备系统
             * 从冒险者身上卸下指定装备
             * 通过装备ID匹配定位装备部位
             * 将装备放回背包并更新属性
             * 提供操作反馈和界面更新
             * 
             * 卸下流程：
             * 1. 将装备添加到冒险者背包
             * 2. 遍历所有装备部位查找匹配装备
             * 3. 通过装备ID精确匹配定位
             * 4. 清空匹配部位的装备引用
             * 5. 记录卸下装备的操作日志
             * 6. 显示卸下装备的通知消息
             * 7. 更新冒险者的装备属性加成
             * 8. 关闭当前装备模态框
             * 9. 重新显示冒险者详情界面
             * 
             * 装备定位：
             * - 遍历所有装备部位对象
             * - 通过装备ID精确匹配
             * - 确保唯一性避免误操作
             * - 找到后立即停止遍历
             * 
             * 数据同步：
             * - 装备在背包和装备栏间转移
             * - 装备部位引用正确清除
             * - 属性加成实时重新计算
             * - 操作日志时间戳记录
             * 
             * 用户体验：
             * - 实时反馈卸下操作结果
             * - 界面自动刷新显示变化
             * - 模态框状态正确管理
             * - 防止重复或无效操作
             * 
             * @param {Object} equipment - 要卸下的装备对象
             * @param {Object} adventurer - 要卸下装备的冒险者对象
             */
            unequipItem(equipment, adventurer) {
                adventurer.inventory.push(equipment);

                for (const slot in adventurer.equipment) {
                    if (adventurer.equipment[slot] && adventurer.equipment[slot].id === equipment.id) {
                        adventurer.equipment[slot] = null;
                        break;
                    }
                }

                adventurer.log.push(`${new Date().toLocaleTimeString()} 卸下了${equipment.name}`);
                this.showNotification(`${adventurer.name}卸下了${equipment.name}`);

                this.updateEquipmentBonuses(adventurer);

                this.hideEquipmentModal();
                this.showAdventurerModal(adventurer);
            }

            /**
             * 出售物品 - 经济系统
             * 将冒险者背包中的装备出售给村庄
             * 计算出售价格并更新金币数量
             * 提供交易反馈和界面更新
             * 
             * 出售流程：
             * 1. 计算装备半价出售金额
             * 2. 增加冒险者金币数量
             * 3. 减少村庄金币储备
             * 4. 从背包中移除装备
             * 5. 记录出售操作日志
             * 6. 显示出售成功通知
             * 7. 关闭装备模态框
             * 8. 重新显示冒险者详情
             * 
             * 价格计算：
             * - 按装备价值50%计算
             * - 向下取整避免小数
             * - 保证村庄金币流动
             * - 维护经济平衡性
             * 
             * 数据更新：
             * - 冒险者金币数量增加
             * - 村庄金币储备减少
             * - 背包物品列表过滤
             * - 操作日志详细记录
             * 
             * 用户体验：
             * - 明确显示出售收益
             * - 实时更新金币显示
             * - 界面自动刷新变化
             * - 操作反馈及时通知
             * 
             * @param {Object} equipment - 要出售的装备对象
             * @param {Object} adventurer - 出售装备的冒险者对象
             */
            sellItem(equipment, adventurer) {
                // 动态定价：出售价格基于装备价值和冒险者总金钱
                const baseSellPrice = Math.floor(equipment.value * 0.5);
                const sellPrice = Math.max(1, Math.floor(baseSellPrice * (1 - adventurer.gold * 0.00005)));
                adventurer.gold += sellPrice;
                this.gold -= sellPrice;

                adventurer.inventory = adventurer.inventory.filter(i => i.id !== equipment.id);

                adventurer.log.push(`${new Date().toLocaleTimeString()} 出售${equipment.name}，获得${sellPrice}金币`);
                this.showNotification(`出售${equipment.name}，获得${sellPrice}金币`);

                this.hideEquipmentModal();
                this.showAdventurerModal(adventurer);
            }

            /**
             * 修理装备 - 装备系统
             * 修复冒险者装备的耐久度
             * 根据装备损坏程度计算修理费用
             * 提供修理反馈和金币消耗
             * 
             * 修理流程：
             * 1. 计算修理费用基于损坏程度
             * 2. 检查冒险者是否有足够金币
             * 3. 如金币充足则恢复装备耐久
             * 4. 扣除冒险者金币并增加村庄收入
             * 5. 记录修理操作日志
             * 6. 显示修理成功或失败通知
             * 7. 关闭装备模态框
             * 8. 重新显示冒险者详情
             * 
             * 费用计算：
             * - 基础费用为装备价值20%
             * - 乘以损坏比例(1-当前耐久/最大耐久)
             * - 向下取整避免小数问题
             * - 损坏越严重修理费用越高
             * 
             * 条件检查：
             * - 验证冒险者金币是否充足
             * - 提供金币不足的错误提示
             * - 修理成功后恢复满耐久
             * - 维护金币流动平衡
             * 
             * 用户体验：
             * - 明确显示修理费用
             * - 提供成功/失败状态反馈
             * - 实时更新装备耐久度
             * - 界面自动刷新显示变化
             * 
             * @param {Object} equipment - 要修理的装备对象
             * @param {Object} adventurer - 要修理装备的冒险者对象
             */
            repairItem(equipment, adventurer) {
                // 动态定价：修理费用基于装备价值和冒险者总金钱
                const baseRepairCost = Math.floor(equipment.value * 0.2 * (1 - equipment.durability / equipment.maxDurability));
                const repairCost = Math.max(1, Math.floor(baseRepairCost * (1 + adventurer.gold * 0.0001)));

                if (adventurer.gold >= repairCost) {
                    equipment.durability = equipment.maxDurability;
                    adventurer.gold -= repairCost;
                    this.gold += repairCost;

                    adventurer.log.push(`${new Date().toLocaleTimeString()} 修理${equipment.name}，花费${repairCost}金币`);
                    this.showNotification(`修理${equipment.name}，花费${repairCost}金币`);
                } else {
                    this.showNotification(`金币不足，无法修理`, 'error');
                }

                this.hideEquipmentModal();
                this.showAdventurerModal(adventurer);
            }

            /**
             * 隐藏冒险者模态框 - UI系统
             * 关闭冒险者详情模态框界面
             * 清除选中冒险者引用
             * 重置模态框显示状态
             * 
             * 关闭流程：
             * 1. 获取冒险者模态框元素
             * 2. 设置CSS显示属性为'none'
             * 3. 清除当前选中的冒险者引用
             * 4. 完成模态框隐藏操作
             * 
             * 界面管理：
             * - 直接操作DOM元素显示属性
             * - 清除对象引用避免内存泄漏
             * - 保持界面状态一致性
             * - 支持模态框重复打开关闭
             * 
             * 数据清理：
             * - 重置选中冒险者状态
             * - 避免残留数据影响后续操作
             * - 维护模态框状态正确性
             * - 确保下次打开时状态干净
             */
            hideAdventurerModal() {
                document.getElementById('modal').style.display = 'none';
                this.selectedAdventurer = null;
            }

            /**
             * 隐藏装备模态框 - UI系统
             * 关闭装备详情模态框界面
             * 清除选中装备引用
             * 重置模态框显示状态
             * 
             * 关闭流程：
             * 1. 获取装备模态框元素
             * 2. 设置CSS显示属性为'none'
             * 3. 清除当前选中的装备引用
             * 4. 完成模态框隐藏操作
             * 
             * 界面管理：
             * - 直接操作DOM元素显示属性
             * - 清除对象引用避免内存泄漏
             * - 保持界面状态一致性
             * - 支持模态框重复打开关闭
             * 
             * 数据清理：
             * - 重置选中装备状态
             * - 避免残留数据影响后续操作
             * - 维护模态框状态正确性
             * - 确保下次打开时状态干净
             */
            hideEquipmentModal() {
                document.getElementById('equipment-modal').style.display = 'none';
                this.selectedEquipment = null;
            }

            /**
             * 游戏主循环函数
             * 基于requestAnimationFrame的高效游戏循环实现
             * 这是游戏的核心驱动函数，负责协调游戏逻辑更新和画面渲染
             * 
             * 循环流程：
             * 1. 计算时间差值（deltaTime）
             * 2. 更新游戏状态（update）
             * 3. 渲染游戏画面（renderTextGame）
             * 4. 递归调用自身以维持循环
             * 
             * 性能优化要点：
             * - 使用时间差值确保游戏速度与帧率无关
             * - 暂停机制避免不必要的计算
             * - 分帧处理减少单帧计算压力
             * 
             * @param {number} timestamp - 当前时间戳（由requestAnimationFrame提供）
             */
            gameLoop(timestamp) {
                // 初始化或更新时间戳 - 确保第一次调用时有正确的时间基准
                if (!this.lastTime) this.lastTime = timestamp;
                
                // 计算时间差值，考虑页面可能在后台的情况
                // deltaTime表示距离上一帧经过的时间（毫秒），乘以游戏速度倍数
                let deltaTime = (timestamp - this.lastTime) * this.gameSpeed;
                this.lastTime = timestamp;

                // 限制最大时间差值，防止页面从后台切换回前台时的跳跃
                // 当页面在后台时，requestAnimationFrame不会被调用，回到前台时deltaTime会很大
                deltaTime = Math.min(deltaTime, 1000);

                // 暂停状态下只渲染不更新逻辑
                // 这样可以节省CPU资源，同时保持UI的响应性
                if (!this.isPaused) {
                    this.update(deltaTime);
                }

                // 渲染游戏画面（文字游戏版本）
                // 即使在暂停状态下也会继续渲染，以保持UI的更新
                this.renderTextGame();
                
                // 递归调用维持游戏循环
                // requestAnimationFrame会在下一次浏览器重绘之前调用gameLoop
                requestAnimationFrame(this.gameLoop.bind(this));
            }

            /**
             * 后台更新函数 - 当页面不可见时使用setTimeout维持游戏逻辑更新
             * 确保挂机游戏体验，即使在其他标签页也能正常进行
             * 优化后台更新频率，提高挂机效率
             */
            backgroundUpdate() {
                this.debugLog('Background update called, document.hidden:', document.hidden, 'backgroundUpdateActive:', this.backgroundUpdateActive);
                // 页面不可见时继续更新游戏逻辑
                const now = Date.now();
                // 提高后台更新频率到200ms，确保更流畅的挂机体验
                const deltaTime = Math.min((now - (this.lastBackgroundUpdate || now)) * this.gameSpeed, 1000);
                this.lastBackgroundUpdate = now;

                // 更新游戏时间
                this.gameTime += deltaTime;

                // 在后台也更新游戏逻辑（保持正常频率以确保挂机效果）
                if (!this.isPaused) {
                    this.update(deltaTime);
                }

                // 渲染游戏画面（文字游戏版本）
                // 即使在后台也保持UI更新
                this.renderTextGame();

                // 提高后台更新频率到200ms，确保更流畅的挂机体验
                // 使用requestIdleCallback（如果可用）来优化性能
                if (this.backgroundUpdateActive && document.hidden) {
                    this.debugLog('Scheduling next background update');
                    if (window.requestIdleCallback) {
                        requestIdleCallback(() => this.backgroundUpdate(), { timeout: 200 });
                    } else {
                        setTimeout(() => this.backgroundUpdate(), 200);
                    }
                } else if (this.backgroundUpdateActive && !document.hidden) {
                    // 如果页面重新可见，切换回requestAnimationFrame
                    this.debugLog('Switching back to requestAnimationFrame');
                    this.backgroundUpdateActive = false;
                    requestAnimationFrame(this.gameLoop.bind(this));
                } else if (this.backgroundUpdateActive) {
                    // 继续后台更新
                    this.debugLog('Continuing background update');
                    if (window.requestIdleCallback) {
                        requestIdleCallback(() => this.backgroundUpdate(), { timeout: 200 });
                    } else {
                        setTimeout(() => this.backgroundUpdate(), 200);
                    }
                } else {
                    this.debugLog('Background update stopped');
                }
            }

            /**
             * 游戏状态更新函数
             * 负责更新游戏世界中的所有对象和系统
             * 这是游戏逻辑的核心方法，按不同频率更新各种游戏系统
             * 
             * 更新顺序和频率优化：
             * 1. 高频更新（每帧）：游戏时间、冒险者、怪物
             * 2. 中频更新（每秒）：UI显示、任务进度
             * 3. 低频更新（定时）：称号检查、税收征收、建筑收入
             * 
             * @param {number} deltaTime - 时间差值（毫秒）
             */
            /**
             * 游戏状态更新方法
             * 负责更新游戏世界中的所有对象和系统状态
             * @param {number} deltaTime - 距离上一帧的时间差（毫秒）
             */
            update(deltaTime) {
                // 更新游戏时间 - 每帧都会更新，用于计算各种定时事件
                this.gameTime += deltaTime;

                // 限制频繁的DOM更新（每秒一次）- 避免过于频繁的UI更新影响性能
                if (this.gameTime % 1000 < deltaTime) {
                    const gameTimeEl = document.getElementById('game-time');
                    if (gameTimeEl) gameTimeEl.textContent = Math.floor(this.gameTime / 1000);
                }

                // 检查称号解锁 - 降低频率以提高性能（每30秒）
                // 称号系统不需要每帧检查，定期检查即可
                if (this.gameTime % 30000 < deltaTime) {
                    this.checkTitleUnlocks();
                }

                // 税收系统 - 保持原有频率（每分钟）
                // 税收是游戏经济的重要组成部分，按固定时间间隔征收
                if (this.gameTime - this.lastTaxTime > this.dailyTaxInterval) {
                    this.collectTaxes();
                    this.lastTaxTime = this.gameTime;
                }
                
                // 更新研究进度 - 保持原有频率（实时）
                // 研究系统需要实时更新进度，给玩家即时反馈
                this.updateResearchProgress(deltaTime);

                // 生成冒险者 - 保持原有频率
                // 根据称号效果调整招募速度，确保村庄有足够的冒险者
                // 降低冒险者生成频率以提高性能
                // 进一步降低生成频率，减少性能压力
                if (Math.random() < 0.05) { // 每帧只有5%概率检查生成
                    const recruitSpeed = this.titleEffects.recruitSpeed || 0;
                    if (this.adventurers.length < Config.MAX_ADVENTURERS + (this.titleEffects.maxAdventurers || 0) &&
                        Math.random() < Config.ADVENTURER_SPAWN_RATE * (1 + recruitSpeed) * 0.5) { // 降低生成率
                        this.createAdventurer();
                    }
                }

                // 生成怪物 - 进一步优化生成频率和密度以支持挂机体验
                // 提高怪物生成率，确保有足够的怪物供冒险者战斗
                // 降低怪物生成频率以提高性能（每帧生成概率降低）
                // 进一步降低生成频率，减少性能压力
                if (Math.random() < 0.03) { // 每帧有3%概率检查生成
                    let baseSpawnRate = Config.MONSTER_SPAWN_RATE * 1.5; // 进一步降低生成率
                    if (this.titleEffects.spawnRate) {
                        baseSpawnRate *= (1 + this.titleEffects.spawnRate);
                    }

                    // 如果怪物数量较少，进一步提高生成率
                    // 动态调整生成率以维持游戏平衡
                    const spawnBonus = this.monsters.length < Config.MONSTER_MAX_COUNT * 0.3 ? 1.5 : 
                                      this.monsters.length < Config.MONSTER_MAX_COUNT * 0.6 ? 1.2 : 1.0;
                    
                    // 根据冒险者数量调整生成率，确保有足够的怪物供战斗
                    const adventurerCountBonus = Math.max(1.1, this.adventurers.length / 10);
                    
                    // 增加一个额外的生成检查，提高怪物刷新频率
                    if ((Math.random() < baseSpawnRate * spawnBonus * adventurerCountBonus && this.monsters.length < Config.MONSTER_MAX_COUNT) ||
                        (this.monsters.length < Config.MONSTER_MAX_COUNT * 0.3 && Math.random() < 0.05)) { // 进一步降低阈值
                        const newMonster = this.createMonster();
                        if (newMonster) {
                            this.debugLog(`生成了新怪物: ${newMonster.rank}${newMonster.type} Lv.${newMonster.level} 在坐标 (${Math.floor(newMonster.x)}, ${Math.floor(newMonster.y)})`);
                        }
                    }
                }
                
                // 批量更新怪物 - 分批处理以避免单帧阻塞（中频）
                // 使用游标记录上一次处理位置，每帧处理有限数量实体
                if (Math.random() < 0.8 && this.monsters.length > 0) { // 80%的概率更新怪物
                    const totalMonsters = this.monsters.length;
                    // 保持每帧处理的怪物数量以实现秒级刷新
                    const batch = Math.min(this.updateBatchSize, totalMonsters);
                    for (let k = 0; k < batch; k++) {
                        // 环绕索引，避免索引越界或重复处理
                        const i = (this.monsterUpdateIndex + k) % totalMonsters;
                        this.updateMonster(this.monsters[i], deltaTime, i);
                    }
                    this.monsterUpdateIndex = (this.monsterUpdateIndex + batch) % Math.max(1, totalMonsters);
                }

                // 批量更新冒险者 - 分批处理以避免单帧阻塞（中频）
                if (Math.random() < 0.8 && this.adventurers.length > 0) { // 80%的概率更新冒险者
                    const totalAdv = this.adventurers.length;
                    // 保持每帧处理的冒险者数量以实现秒级刷新
                    const batchA = Math.min(this.updateBatchSize, totalAdv);
                    for (let k = 0; k < batchA; k++) {
                        const i = (this.adventurerUpdateIndex + k) % totalAdv;
                        this.updateAdventurer(this.adventurers[i], deltaTime);
                    }
                    this.adventurerUpdateIndex = (this.adventurerUpdateIndex + batchA) % Math.max(1, totalAdv);
                }

                // 更新建筑 - 提高频率以实现秒级刷新（每1秒）
                // 为了满足用户需求，提高建筑更新频率到每秒一次
                if (this.gameTime % 1000 < deltaTime) {
                    this.updateBuildings(deltaTime);
                }
                
                // 恢复冒险者MP - 提高恢复速度以支持更频繁的技能使用
                // 保持更新频率以实现秒级刷新
                if (Math.random() < 0.7 && this.adventurers.length > 0) { // 70%的概率更新MP恢复
                    const totalAdvMp = this.adventurers.length;
                    // 保持每帧处理的冒险者数量以实现秒级刷新
                    const batchMp = Math.min(this.updateBatchSize, totalAdvMp);
                    for (let k = 0; k < batchMp; k++) {
                        const i = (this.adventurerUpdateIndex + k) % totalAdvMp;
                        const adventurer = this.adventurers[i];
                        if (adventurer && adventurer.state !== 'dead' && adventurer.mp < adventurer.maxMp) {
                            // 每秒恢复3%最大MP
                            adventurer.mp = Math.min(adventurer.maxMp, adventurer.mp + (adventurer.maxMp * 0.03 * deltaTime / 1000));
                        }
                    }
                    // 不移动 adventurerUpdateIndex，这里只是短期遍历当前批次
                }
                
                // 慈善系统 - 保持原有频率（每30秒）
                // 定期向贫困冒险者提供援助，维持游戏平衡
                if (this.gameTime % 30000 < deltaTime) {
                    this.provideCharityAid();
                }
                
                // 紧急援助系统 - 保持原有频率（每10秒）
                // 对处于危险状态的冒险者提供紧急援助
                if (this.gameTime % 10000 < deltaTime) {
                    this.provideEmergencyAid();
                }
                
                // 定期更新任务进度 - 降低频率以提高性能（每5秒）
                // 任务进度不需要实时更新，定期检查即可
                if (this.gameTime % 5000 < deltaTime) {
                    this.updateQuestProgress('gold', 0); // 金币任务不累加，直接设置
                }

                // 定期清理长时间未被击败的怪物 - 每30秒检查一次
                // 防止内存泄漏，清理5分钟内未被击败的怪物
                if (this.gameTime % 30000 < deltaTime) {
                    this.cleanupOldMonsters();
                }

                // 定期更新UI - 提高频率以实现秒级刷新（每1秒）
                // 为了满足用户需求，提高UI更新频率到每秒一次
                if (this.gameTime % 1000 < deltaTime) {
                    this.updateUI();
                    // 更新当前活跃页签的内容
                    const activeTab = document.querySelector('.tab-btn.active');
                    if (activeTab) {
                        const tabName = activeTab.getAttribute('data-tab');
                        this.updateTabContent(tabName);
                    }
                }
                
                // 降低其他UI更新频率以平衡性能
                if (this.gameTime % 5000 < deltaTime) {
                    // 更新任务和研究显示
                    this.updateQuestDisplay();
                    this.updateResearchDisplay();
                    
                    // 更新建筑按钮状态
                    this.updateBuildingButtonStates();
                }
            }

            /**
             * 征收税收 - 调整版
             * 每天收取冒险者自身金钱的1%
             */
            collectTaxes() {
                let totalTax = 0;
                // 使用for循环替代forEach以提高性能
                for (let i = this.adventurers.length - 1; i >= 0; i--) {
                    const adventurer = this.adventurers[i];
                    // 添加金币安全检查
                    adventurer.gold = Math.max(0, adventurer.gold);
                    
                    // 每天收取冒险者自身金钱的1%
                    const tax = Math.min(adventurer.gold, Math.floor(adventurer.gold * 0.01));
                    adventurer.gold = Math.max(0, adventurer.gold - tax);
                    totalTax += tax;
                }

                if (totalTax > 0) {
                    // 确保金币不会溢出
                    this.gold = Math.max(0, this.gold + totalTax);
                    this.taxRevenue += totalTax;
                    this.totalTaxCollected += totalTax;
                    this.showNotification(`征收税收：${totalTax}金币`, 'success');
                    this.addLogEntry(`征收税收：${totalTax}金币`, 'success');
                }
            }

            /**
             * 冒险者AI决策系统 - 核心状态机
             * 
             * 冒险者具有复杂的行为决策系统，基于优先级和状态评估
             * 这是冒险者AI的核心方法，负责处理冒险者的各种行为和状态转换
             * 
             * 状态优先级（从高到低）：
             * 1. 死亡状态 - 特殊处理
             * 2. 战斗冷却期 - 限制行为
             * 3. 急性生存需求 - 饥饿、生命危险
             * 4. 受伤状态 - 优先治疗
             * 5. 正常状态 - 日常活动
             * 
             * 决策流程：
             * 1. 状态验证和防死锁处理
             * 2. 紧急需求检查
             * 3. 资源状态评估
             * 4. 行为选择和执行
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态
             * @param {number} deltaTime - 时间差值（毫秒），用于计算各种时间相关的变化
             */
            updateAdventurer(adventurer, deltaTime) {
                // === 金币安全检查：防止负值 ===
                // 确保冒险者的金币不会出现负数
                adventurer.gold = Math.max(0, adventurer.gold);
                
                // === 更新饥饿值 ===
                // 根据时间流逝减少冒险者的饥饿值
                adventurer.hunger = Math.max(0, adventurer.hunger - Config.HUNGER_DECREASE_RATE * deltaTime);

                // === 饥饿系统 - 改进保护机制 ===
                // 当冒险者极度饥饿时，开始受到饥饿伤害
                if (adventurer.hunger <= Config.HUNGER_STARVING) {
                    // 饥饿伤害渐进式增加，越饥饿伤害越高
                    // 这样设计是为了避免冒险者瞬间死亡，给玩家反应时间
                    const hungerDamage = Math.max(0.05, (Config.HUNGER_STARVING - adventurer.hunger) * 0.02) * deltaTime;
                    
                    // 生命值保护机制：最低保持在最大生命值的10%，但不会死亡
                    // 防止冒险者因饥饿而直接死亡，保持游戏平衡
                    const minHp = Math.max(5, adventurer.maxHp * 0.1);
                    adventurer.hp = Math.max(minHp, adventurer.hp - hungerDamage);
                    
                    // 每5秒发送一次饥饿警告，避免日志过于冗长
                    if (Date.now() - (adventurer.lastHungerWarning || 0) > 5000) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 饥饿过度，生命值持续下降（剩余${Math.floor(adventurer.hp)}点）`);
                        adventurer.lastHungerWarning = Date.now();
                        
                        // 饥饿至极限时强制停止战斗，避免冒险者在极度饥饿状态下继续战斗
                        if (adventurer.state === 'fighting' && adventurer.hunger <= 5) {
                            adventurer.target = null;
                            adventurer.state = 'idle';
                            adventurer.combatCooldown = Date.now() + 10000; // 10秒冷却
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 极度饥饿，被迫停止战斗`);
                        }
                    }
                }

                // === 死亡检查和处理 - 改进版本 ===
                // 检查冒险者是否死亡（生命值为0且不处于极度饥饿状态）
                if (adventurer.hp <= 0 && adventurer.hunger > Config.HUNGER_STARVING) {
                    // 死亡惩罚 - 添加安全检查，防止金币出现负值
                    const goldLoss = Math.min(adventurer.gold, Math.floor(adventurer.gold * Config.DEATH_PENALTY));
                    adventurer.gold = Math.max(0, adventurer.gold - goldLoss);
                    this.gold = Math.max(0, this.gold + goldLoss); // 村庄获得死亡冒险者的金币

                    // 记录死亡时间并设置状态为死亡
                    if (!adventurer.deathTime) {
                        adventurer.deathTime = Date.now();
                        adventurer.state = 'dead';
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 不幸阵亡，损失${goldLoss}金币`);
                    } 
                    // 检查是否达到复活时间
                    else if (Date.now() - adventurer.deathTime > Config.RESPAWN_TIME) {
                        // 复活 - 恢复部分生命值和饥饿值
                        adventurer.hp = adventurer.maxHp * 0.5;
                        adventurer.hunger = Math.max(adventurer.hunger, adventurer.maxHunger * 0.3); // 复活时恢复一些饥饿值
                        adventurer.deathTime = null;
                        adventurer.state = 'idle';
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 复活了`);
                    }
                    return; // 死亡状态下不执行后续逻辑
                }
                
                // === 死亡状态安全检查 ===
                // 防止冒险者卡在死亡状态无法复活
                if (adventurer.state === 'dead') {
                    // 如果死亡时间过长，强制复活以防止永久卡死
                    if (!adventurer.deathTime || Date.now() - adventurer.deathTime > Config.RESPAWN_TIME * 2) {
                        // 强制复活，防止永久卡死
                        this.debugLog(`冒险者 ${adventurer.name} 死亡状态超时，强制复活`);
                        adventurer.hp = adventurer.maxHp * 0.3;
                        adventurer.hunger = Math.max(adventurer.hunger, adventurer.maxHunger * 0.2);
                        adventurer.deathTime = null;
                        adventurer.state = 'idle';
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 强制复活`);
                    }
                    return; // 死亡状态下不执行后续逻辑
                }

                // 检查转职条件 - 当冒险者达到指定等级时解锁转职功能
                if (adventurer.level >= adventurer.classChangeLevel && !adventurer.canChangeClass) {
                    adventurer.canChangeClass = true;
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 已达到转职条件，可以转职了！`);
                }

                // 清理过期的技能冷却时间 - 移除已经结束冷却的技能
                const now = Date.now();
                for (const skill in adventurer.skillCooldowns) {
                    if (adventurer.skillCooldowns[skill] < now) {
                        delete adventurer.skillCooldowns[skill];
                    }
                }

                // 清理过长的日志记录 - 限制每个冒险者的日志数量，避免内存泄漏
                // 保留最近的100条日志，防止日志无限增长
                if (adventurer.log.length > 100) {
                    adventurer.log = adventurer.log.slice(-100);
                }

                // === AI状态机 - 防死锁处理 ===
                // 定义有效的状态列表，用于状态验证
                const validStates = ['idle', 'moving', 'fighting', 'resting', 'eating', 'shopping', 'repairing', 'upgrading', 'wandering', 'emergency_rest', 'field_rest', 'enchanting', 'alchemy', 'dead'];
                
                // 状态验证：如果状态无效，重置为idle
                if (!validStates.includes(adventurer.state)) {
                    this.debugLog(`冒险者 ${adventurer.name} 状态异常: ${adventurer.state}，重置为idle`);
                    adventurer.state = 'idle';
                }
                
                // 状态持续时间检查：防止状态卡死
                // 确保每个状态都有开始时间记录
                if (!adventurer.stateStartTime) {
                    adventurer.stateStartTime = Date.now();
                }
                
                // 定义各个状态的最大持续时间，防止冒险者卡在某个状态
                const stateMaxDuration = {
                    'moving': 30000,      // 移动最长30秒
                    'fighting': 60000,    // 战斗最长60秒
                    'resting': 20000,     // 休息最长20秒
                    'eating': 10000,      // 吃饭最长10秒
                    'shopping': 15000,    // 购物最长15秒
                    'repairing': 10000,   // 修理最长10秒
                    'upgrading': 15000,   // 升级最长15秒
                    'wandering': 45000,   // 游荡最长45秒
                    'emergency_rest': 15000, // 紧急休息最长15秒（增加时间）
                    'field_rest': 20000,  // 就地休息最长20秒（增加时间）
                    'enchanting': 15000,  // 附魔最长15秒
                    'alchemy': 15000      // 炼金术最长15秒
                };
                
                // 计算当前状态已持续的时间
                const stateDuration = Date.now() - adventurer.stateStartTime;
                const maxDuration = stateMaxDuration[adventurer.state];
                
                // 检查是否超过最大持续时间
                if (maxDuration && stateDuration > maxDuration) {
                    this.debugLog(`冒险者 ${adventurer.name} 状态 ${adventurer.state} 超时，根据状态类型进行智能恢复`);
                    
                    // 根据超时状态类型进行智能恢复
                    switch(adventurer.state) {
                        case 'emergency_rest':
                        case 'field_rest':
                            // 休息状态超时，检查是否已恢复到安全水平
                            if (adventurer.hp >= adventurer.maxHp * 0.3) {
                                adventurer.state = 'idle';
                            } else {
                                // 仍未恢复，继续休息
                                adventurer.stateStartTime = Date.now(); // 重置计时器
                                break;
                            }
                            break;
                        case 'moving':
                            // 移动状态超时，可能是卡住了，重置目标
                            this.debugLog(`冒险者 ${adventurer.name} 移动状态超时，重置目标`);
                            adventurer.target = null;
                            adventurer.targetX = null;
                            adventurer.targetY = null;
                            adventurer.state = 'idle';
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 移动超时，重新规划路径`);
                            break;
                        default:
                            // 其他状态超时，重置为idle
                            adventurer.state = 'idle';
                            adventurer.target = null;
                            adventurer.targetX = null;
                            adventurer.targetY = null;
                            break;
                    }
                    
                    adventurer.stateStartTime = Date.now();
                    // 立即调用idle处理函数，确保冒险者有新的行为
                    this.updateAdventurerIdle(adventurer);
                }
                
                // 根据状态更新冒险者行为 - 状态机的核心逻辑
                switch(adventurer.state) {
                    case 'idle':
                        adventurer.stateStartTime = Date.now(); // idle状态重置计时器
                        this.updateAdventurerIdle(adventurer);
                        break;
                    case 'moving':
                        this.updateAdventurerMoving(adventurer, deltaTime);
                        break;
                    case 'fighting':
                        this.updateAdventurerFighting(adventurer, deltaTime);
                        break;
                    case 'resting':
                        this.updateAdventurerResting(adventurer, deltaTime);
                        break;
                    case 'eating':
                        this.updateAdventurerEating(adventurer, deltaTime);
                        break;
                    case 'shopping':
                        this.updateAdventurerShopping(adventurer, deltaTime);
                        break;
                    case 'repairing':
                        this.updateAdventurerRepairing(adventurer, deltaTime);
                        break;
                    case 'upgrading':
                        this.updateAdventurerUpgrading(adventurer, deltaTime);
                        break;
                    case 'wandering':
                        this.updateAdventurerWandering(adventurer, deltaTime);
                        break;
                    case 'emergency_rest':
                        this.updateAdventurerEmergencyRest(adventurer, deltaTime);
                        break;
                    case 'field_rest':
                        this.updateAdventurerFieldRest(adventurer, deltaTime);
                        break;
                    case 'enchanting':
                        this.updateAdventurerEnchanting(adventurer, deltaTime);
                        break;
                    case 'alchemy':
                        this.updateAdventurerAlchemy(adventurer, deltaTime);
                        break;
                    case 'dead':
                        // 死亡状态不需要额外处理
                        break;
                    default:
                        // 未知状态，强制重置
                        adventurer.state = 'idle';
                        adventurer.stateStartTime = Date.now();
                        break;
                }

                // === 装备系统 - 改进版本检查 ===
                // 检查装备耐久度并处理相关逻辑
                this.checkEquipmentDurabilityImproved(adventurer);
                // 检查套装加成效果
                this.checkSetBonuses(adventurer);

                // === 库存管理 - 防止溢出 ===
                // 当背包物品超过20个时，自动出售低价值物品
                if (adventurer.inventory && adventurer.inventory.length > 20) {
                    this.sellExcessItems(adventurer);
                }

                // === 自动装备和属性更新 ===
                // 自动装备更好的物品
                this.autoEquipBetterItems(adventurer);
                // 更新装备提供的属性加成
                this.updateEquipmentBonuses(adventurer);
            }

            /**
             * 改进的装备耐久度检查 - 修复原版BUG
             * 确保装备耐久度不会出现异常值，并在需要时触发修理行为
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 检查装备耐久度状态 - 智能监控系统
             * 实时监控冒险者所有装备的耐久度状态，提供分级预警和详细通知
             * 支持智能决策系统获取装备状态信息
             * 
             * 监控机制：
             * 1. 实时检查所有装备耐久度状态
             * 2. 分级预警系统（紧急/警告/提醒）
             * 3. 状态变化检测避免重复通知
             * 4. 装备重要性分级处理
             * 5. 详细状态信息记录
             * 
             * 预警等级：
             * - 紧急（红色）：耐久度<5%或已损坏
             * - 警告（橙色）：耐久度<15%（核心装备）或<10%（一般装备）
             * - 提醒（黄色）：耐久度<25%（核心装备）或<15%（一般装备）
             * - 正常（绿色）：耐久度充足
             * 
             * 通知机制：
             * 1. 状态变化检测避免重复通知
             * 2. 首次进入预警状态时记录日志
             * 3. 离开预警状态时重置通知标记
             * 4. 提供详细的耐久度信息和建议
             * 
             * 装备重要性分级：
             * - 核心装备：武器、胸甲（高优先级监控）
             * - 重要装备：头盔、护手、护腿、靴子
             * - 一般装备：饰品（戒指、项链、腰带、护符）
             * 
             * 数据处理：
             * - 自动修复异常耐久度值
             * - 确保耐久度在合理范围内
             * - 提供准确的状态信息
             * - 支持状态持久化
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            checkEquipmentDurabilityImproved(adventurer) {
                // 安全检查：确保冒险者和装备对象存在
                if (!adventurer || !adventurer.equipment) return;
                
                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    
                    // 检查装备是否存在
                    if (!equipment) continue;
                    
                    // 确保装备有耐久度属性
                    if (typeof equipment.durability === 'undefined' || typeof equipment.maxDurability === 'undefined') {
                        equipment.durability = equipment.maxDurability || 100;
                        equipment.maxDurability = equipment.maxDurability || 100;
                    }
                    
                    // 修复异常的耐久度值
                    if (equipment.durability < 0) equipment.durability = 0;
                    if (equipment.durability > equipment.maxDurability) equipment.durability = equipment.maxDurability;
                    
                    // 计算耐久度比例
                    const durabilityRatio = equipment.durability / equipment.maxDurability;
                    const durabilityPercent = Math.floor(durabilityRatio * 100);
                    
                    // 根据装备类型确定重要性等级
                    const isCoreEquipment = ['武器', '胸甲'].includes(equipment.slot);
                    const isImportantEquipment = ['头盔', '护手', '护腿', '靴子'].includes(equipment.slot);
                    
                    // 确定预警等级
                    let warningLevel = 'normal'; // normal, reminder, warning, emergency
                    let shouldNotify = false;
                    
                    if (durabilityRatio <= 0) {
                        // 装备已完全损坏
                        warningLevel = 'emergency';
                        shouldNotify = !equipment.brokenNotified;
                        equipment.brokenNotified = true;
                        equipment.lowDurabilityNotified = false; // 重置其他通知状态
                        equipment.reminderNotified = false;
                        equipment.warningNotified = false;
                    } else if (durabilityRatio < 0.05) {
                        // 紧急情况：任何装备耐久度低于5%
                        warningLevel = 'emergency';
                        shouldNotify = !equipment.emergencyNotified;
                        equipment.emergencyNotified = true;
                        equipment.brokenNotified = false; // 重置其他通知状态
                        equipment.lowDurabilityNotified = false;
                        equipment.reminderNotified = false;
                        equipment.warningNotified = false;
                    } else if ((isCoreEquipment && durabilityRatio < 0.15) || 
                               (!isCoreEquipment && durabilityRatio < 0.10)) {
                        // 警告状态：核心装备<15%或一般装备<10%
                        warningLevel = 'warning';
                        shouldNotify = !equipment.warningNotified;
                        equipment.warningNotified = true;
                        equipment.brokenNotified = false; // 重置其他通知状态
                        equipment.emergencyNotified = false;
                        equipment.lowDurabilityNotified = false;
                        equipment.reminderNotified = false;
                    } else if ((isCoreEquipment && durabilityRatio < 0.25) || 
                               (!isCoreEquipment && durabilityRatio < 0.15)) {
                        // 提醒状态：核心装备<25%或一般装备<15%
                        warningLevel = 'reminder';
                        shouldNotify = !equipment.reminderNotified;
                        equipment.reminderNotified = true;
                        equipment.brokenNotified = false; // 重置其他通知状态
                        equipment.emergencyNotified = false;
                        equipment.lowDurabilityNotified = false;
                        equipment.warningNotified = false;
                    } else {
                        // 正常状态：重置所有通知标记
                        equipment.brokenNotified = false;
                        equipment.emergencyNotified = false;
                        equipment.warningNotified = false;
                        equipment.reminderNotified = false;
                        equipment.lowDurabilityNotified = false;
                    }
                    
                    // 根据预警等级记录详细日志
                    if (shouldNotify) {
                        let message = `${new Date().toLocaleTimeString()} ${equipment.name}(${equipment.slot})`;
                        let levelText = '';
                        let levelColor = '';
                        
                        switch(warningLevel) {
                            case 'emergency':
                                levelText = '【紧急】';
                                levelColor = '红色';
                                if (durabilityRatio <= 0) {
                                    message += `已完全损坏，急需修理！当前耐久度: ${equipment.durability}/${equipment.maxDurability}(${durabilityPercent}%)`;
                                } else {
                                    message += `耐久度极低，急需修理！当前耐久度: ${equipment.durability}/${equipment.maxDurability}(${durabilityPercent}%)`;
                                }
                                break;
                            case 'warning':
                                levelText = '【警告】';
                                levelColor = '橙色';
                                message += `耐久度较低，建议尽快修理。当前耐久度: ${equipment.durability}/${equipment.maxDurability}(${durabilityPercent}%)`;
                                break;
                            case 'reminder':
                                levelText = '【提醒】';
                                levelColor = '黄色';
                                message += `耐久度偏低，可以考虑修理。当前耐久度: ${equipment.durability}/${equipment.maxDurability}(${durabilityPercent}%)`;
                                break;
                        }
                        
                        if (warningLevel !== 'normal') {
                            // 添加修理建议
                            const repairCost = Math.floor(equipment.value * 0.2 * (1 - durabilityRatio));
                            message += ` 预计修理费用: ${repairCost}金币`;
                            
                            // 根据装备重要性添加优先级建议
                            if (isCoreEquipment) {
                                message += ' [高优先级]';
                            } else if (isImportantEquipment) {
                                message += ' [中优先级]';
                            } else {
                                message += ' [低优先级]';
                            }
                            
                            adventurer.log.push(message);
                        }
                    }
                }
            }

            /**
             * 自动修理装备方法 - 装备维护系统
             * 智能判断并自动前往商店修理低耐久度装备
             * 根据装备类型选择合适的商店，确保修理效率
             * 
             * 修理决策逻辑：
             * 1. 遍历所有装备槽位检查耐久度
             * 2. 优先修理耐久度最低的装备
             * 3. 根据装备类型选择对应商店
             * 4. 检查修理费用和金币是否充足
             * 5. 设置修理目标并改变冒险者状态
             * 
             * 商店选择策略：
             * - 武器类装备：武器店
             * - 防具类装备：防具店
             * - 饰品类装备：武器店
             * 
             * 费用计算机制：
             * - 修理费用 = 装备价值 × 0.2 × (1 - 当前耐久度/最大耐久度)
             * - 耐久度越低费用越高
             * - 价值越高质量越好
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {boolean} 是否成功开始修理装备
             */
            /**
             * 自动修理装备方法 - 智能装备维护系统
             * 智能判断并自动前往商店修理低耐久度装备
             * 根据装备价值、重要性和紧急程度优化修理决策
             * 
             * 修理决策优化：
             * 1. 综合评估装备重要性（价值、稀有度、槽位）
             * 2. 优先修理高价值和关键装备
             * 3. 考虑修理费用与装备价值的性价比
             * 4. 智能选择最近且合适的商店
             * 5. 金币不足时优先修理最重要的装备
             * 
             * 装备优先级评估：
             * - 高优先级：武器（攻击力核心）、胸甲（防御力核心）
             * - 中优先级：头盔、护手、护腿、靴子
             * - 低优先级：饰品（戒指、项链、腰带、护符）
             * - 价值加成：高价值装备优先修理
             * - 稀有度加成：高稀有度装备优先修理
             * 
             * 商店选择策略：
             * - 武器类装备：武器店
             * - 防具类装备：防具店
             * - 饰品类装备：武器店
             * 
             * 费用效益分析：
             * - 修理费用 = 装备价值 × 0.2 × (1 - 当前耐久度/最大耐久度)
             * - 性价比 = 装备价值 / 修理费用
             * - 优先修理高性价比装备
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {boolean} 是否成功开始修理装备
             */
            autoRepairEquipment(adventurer) {
                // 收集所有需要修理的装备
                const equipmentToRepair = [];
                
                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    if (!equipment) continue;
                    
                    // 计算耐久度比例
                    const durabilityRatio = equipment.durability / equipment.maxDurability;
                    
                    // 根据装备类型确定修理阈值
                    let repairThreshold = 0.2; // 默认20%阈值
                    if (['戒指', '项链', '腰带', '护符'].includes(equipment.slot)) {
                        repairThreshold = 0.1; // 饰品10%阈值
                    }
                    
                    // 紧急情况：任何装备耐久度低于5%
                    if (durabilityRatio < 0.05) {
                        repairThreshold = 1.0; // 立即修理
                    }
                    
                    // 如果耐久度低于阈值，添加到待修理列表
                    if (durabilityRatio < repairThreshold) {
                        // 计算修理费用 - 动态定价基于装备价值和冒险者总金钱
                        const baseRepairCost = Math.floor(equipment.value * 0.2 * (1 - durabilityRatio));
                        const repairCost = Math.max(1, Math.floor(baseRepairCost * (1 + adventurer.gold * 0.0001)));
                        
                        // 计算装备优先级评分
                        let priorityScore = 0;
                        
                        // 1. 装备槽位优先级
                        if (['武器', '胸甲'].includes(equipment.slot)) {
                            priorityScore += 100; // 核心装备最高优先级
                        } else if (['头盔', '护手', '护腿', '靴子'].includes(equipment.slot)) {
                            priorityScore += 50; // 一般防具中等优先级
                        } else {
                            priorityScore += 20; // 饰品较低优先级
                        }
                        
                        // 2. 装备价值权重
                        priorityScore += equipment.value / 100;
                        
                        // 3. 装备稀有度权重
                        const rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(equipment.rarity);
                        priorityScore += rarityIndex * 10;
                        
                        // 4. 紧急程度权重（耐久度越低优先级越高）
                        priorityScore += (1 - durabilityRatio) * 50;
                        
                        // 5. 性价比权重（修理费用越低相对优先级越高）
                        if (repairCost > 0) {
                            priorityScore += (equipment.value / repairCost) * 10;
                        }
                        
                        equipmentToRepair.push({
                            equipment: equipment,
                            repairCost: repairCost,
                            priorityScore: priorityScore,
                            durabilityRatio: durabilityRatio
                        });
                    }
                }
                
                // 如果没有需要修理的装备，返回false
                if (equipmentToRepair.length === 0) {
                    return false;
                }
                
                // 按优先级评分排序（高分优先）
                equipmentToRepair.sort((a, b) => b.priorityScore - a.priorityScore);
                
                // 尝试修理优先级最高的装备
                for (const repairItem of equipmentToRepair) {
                    const equipment = repairItem.equipment;
                    const repairCost = repairItem.repairCost;
                    
                    // 根据装备类型选择合适的商店
                    let shopType = '';
                    if (['武器', '戒指', '项链', '腰带', '护符'].includes(equipment.slot)) {
                        shopType = '武器店';
                    } else {
                        shopType = '防具店';
                    }

                    // 查找最近的对应商店
                    const shop = this.findNearestBuilding(shopType, adventurer);
                    if (shop) {
                        // 检查金币是否充足
                        if (adventurer.gold >= repairCost) {
                            // 设置修理目标并改变状态
                            adventurer.target = shop;
                            adventurer.state = 'moving';
                            adventurer.repairTarget = equipment;
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 自动修理${equipment.name}(${Math.floor(repairItem.durabilityRatio * 100)}%耐久度)，前往${shopType}，费用${repairCost}金币`);
                            return true;
                        } else {
                            // 金币不足时记录日志并尝试下一个装备
                            adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}需要修理但金币不足(${adventurer.gold}/${repairCost})`);
                            continue;
                        }
                    } else {
                        // 没有找到商店时记录日志并尝试下一个装备
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}需要修理但未找到${shopType}`);
                        continue;
                    }
                }
                
                // 如果所有装备都无法修理，返回false
                return false;
            }

            /**
             * 更新冒险者空闲状态 - 优化版本
             * 使用清晰的优先级系统处理AI决策，避免冲突和循环
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 冒险者空闲状态处理 - 核心决策方法
             * 当冒险者处于空闲状态时，根据当前状态和需求决定下一步行为
             * 采用多优先级决策系统，确保冒险者在各种情况下都能做出合理的行为选择
             * 
             * 决策优先级顺序：
             * 1. 战斗冷却期间的行为限制（防止连续战斗）
             * 2. 急性生存需求检查（饥饿、生命危险等）
             * 3. 受伤状态特殊处理（优先恢复生命值）
             * 4. 正常状态的优先级处理（日常活动决策）
             * 5. 保底机制（确保冒险者不会卡在空闲状态）
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态信息
             */
            updateAdventurerIdle(adventurer) {
                // 确保stateStartTime已设置 - 用于状态持续时间计算
                if (!adventurer.stateStartTime) {
                    adventurer.stateStartTime = Date.now();
                }
                
                // === 优先级0: 战斗冷却期间的行为限制 ===
                // 当冒险者刚结束战斗时，需要冷却一段时间才能进行下一次战斗
                // 在冷却期间，只能进行非战斗活动（如进食、休息等）
                if (adventurer.combatCooldown && Date.now() < adventurer.combatCooldown) {
                    this.handleCombatCooldownBehavior(adventurer);
                    return; // 处理完冷却期行为后直接返回，不执行后续逻辑
                }

                // 短期移动冷却：当冒险者刚被判定为卡住并重置目标后，避免立即被重新选为目标
                if (adventurer.moveCooldown && Date.now() < adventurer.moveCooldown) {
                    // 在移动冷却期间优先做短暂游荡或等待，减少重复卡住
                    if (Math.random() < 0.5) {
                        this.startWandering(adventurer);
                    } else {
                        // 等待一小段时间再尝试选目标
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 移动冷却中，等待短暂时间`);
                    }
                    return;
                }
                
                // === 优先级1: 急性生存需求检查 ===
                // 检查冒险者是否面临紧急生存威胁（如极度饥饿、生命危险等）
                // 这些情况需要立即处理，优先级最高
                if (this.handleEmergencySurvival(adventurer)) {
                    return; // 处理完紧急生存需求后直接返回
                }
                
                // === 优先级2: 受伤状态特殊处理 ===
                // 当冒险者受伤时（生命值低于30%），需要特殊处理逻辑
                // 受伤状态下会调整行为优先级，优先恢复生命值
                if (this.handleInjuredState(adventurer)) {
                    return; // 处理完受伤状态后直接返回
                }
                
                // === 优先级3: 正常状态的优先级处理 ===
                // 当冒险者处于正常状态时，按照日常活动优先级进行决策
                // 包括装备修理、进食、战斗、购物等日常活动
                this.handleNormalStatePriorities(adventurer);
                
                // === 保底机制：确保冒险者总是有行为 ===
                // 如果经过所有优先级处理后冒险者仍然处于空闲状态
                // 强制进行探索式游荡，确保游戏的动态性
                if (adventurer.state === 'idle') {
                    // 如果经过所有优先级处理后仍然是idle状态，强制进行探索
                    this.startExplorationWander(adventurer);
                }
            }
            
            /**
             * 处理战斗冷却期间的行为
             * 当冒险者刚结束战斗时，需要冷却一段时间才能进行下一次战斗
             * 在冷却期间，只能进行非战斗活动以恢复状态
             * 
             * 冷却期间的优先级行为：
             * 1. 极度饥饿时优先进食（恢复基础状态）
             * 2. 生命值过低时前往旅馆休息（恢复生命值）
             * 3. 就地休息（基础恢复）
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态信息
             */
            handleCombatCooldownBehavior(adventurer) {
                // 冷却期间只能进行非战斗活动
                // 优先处理极度饥饿状态，确保基础生存需求
                if (adventurer.hunger <= Config.HUNGER_CRITICAL) {
                    // 寻找最近的饭店进行进食
                    const restaurant = this.findNearestBuilding('饭店', adventurer);
                    const foodCost = Config.BUILDING_FUNCTIONS['饭店'].cost;
                    // 确保找到饭店且有足够的金币支付费用
                    if (restaurant && adventurer.gold >= foodCost) {
                        adventurer.target = restaurant; // 设置目标为饭店
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 冷却期间优先进食恢复`);
                        return; // 执行完进食行为后直接返回
                    }
                }
                
                // 如果生命值过低（低于最大生命值的50%），前往旅馆休息恢复
                if (adventurer.hp < adventurer.maxHp * 0.5) {
                    // 寻找最近的旅馆进行休息
                    const inn = this.findNearestBuilding('旅馆', adventurer);
                    // 确保找到旅馆且有足够的金币支付费用（10金币）
                    if (inn && adventurer.gold >= 10) {
                        adventurer.target = inn; // 设置目标为旅馆
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 冷却期间前往旅馆休息`);
                        return; // 执行完休息行为后直接返回
                    }
                }
                
                // 如果没有紧急需求，冷却期间就地休息恢复
                // 这是冷却期间的基础恢复行为
                this.startFieldRest(adventurer);
            }
            
            /**
             * 处理急性生存需求（极度饥饿或生命危险）
             * 当冒险者面临生存威胁时，需要立即处理以避免死亡
             * 这是冒险者AI决策系统中的最高优先级处理方法
             * 
             * 生存威胁类型及处理方式：
             * 1. 极度饥饿（饥饿值≤临界值）- 立即寻找食物
             * 2. 生命危险（生命值≤最大生命值的10%）- 立即紧急休息
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态信息
             * @returns {boolean} 是否处理了紧急情况，true表示已处理，false表示无紧急情况
             */
            handleEmergencySurvival(adventurer) {
                // 检查是否需要紧急进食（饥饿值过低）
                // 当饥饿值低于临界值时，冒险者会受到持续伤害，需要立即处理
                if (adventurer.hunger <= Config.HUNGER_CRITICAL) {
                    // 寻找最近的饭店进行进食恢复
                    const restaurant = this.findNearestBuilding('饭店', adventurer);
                    const foodCost = Config.BUILDING_FUNCTIONS['饭店'].cost;
                    
                    // 如果找到饭店且有足够的金币支付费用
                    if (restaurant && adventurer.gold >= foodCost) {
                        adventurer.target = restaurant; // 设置目标为饭店
                        adventurer.state = 'moving'; // 改变状态为移动
                        
                        // 受伤状态下设置特殊治疗标记，用于后续处理
                        const isInjured = adventurer.hp < adventurer.maxHp * 0.3;
                        if (isInjured) {
                            adventurer.treatmentType = 'food'; // 标记为治疗性进食
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤且饥饿，前往饭店进行营养恢复`);
                        } else {
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 饥饿过度，前往饭店进食`);
                        }
                        return true; // 已处理紧急进食需求，返回true
                    } else {
                        // 金币不足或没有饭店，寻找应急食物（野外食物）
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 饥饿但无法前往饭店（金币${adventurer.gold}/${foodCost}），尝试寻找野外食物`);
                        this.tryEmergencyFood(adventurer); // 寻找应急食物
                        return true; // 已处理紧急进食需求，返回true
                    }
                }
                
                // 检查是否处于生命危险状态（生命值极低）
                // 当生命值低于最大生命值的10%时，冒险者面临死亡风险
                if (adventurer.hp <= adventurer.maxHp * 0.1) {
                    // 立即停止所有行动，进入紧急休息状态
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 生命危险！立即停止所有行动，紧急休息`);
                    this.startEmergencyRest(adventurer); // 启动紧急休息
                    return true; // 已处理生命危险，返回true
                }
                
                // 没有紧急生存需求，返回false
                return false;
            }
            
            /**
             * 处理受伤状态的特殊逻辑
             * 当冒险者受伤时（生命值低于30%），需要采用特殊的保守策略
             * 受伤状态下会调整行为优先级，优先恢复生命值和处理相关需求
             * 
             * 受伤状态处理策略：
             * 1. 重伤处理（生命值<15%）- 立即寻求治疗
             * 2. 轻伤处理（生命值<30%）- 优先级调整
             *    a. 饥饿优先级提高
             *    b. 优先修理装备
             *    c. 寻求医疗治疗
             *    d. 低风险战斗
             *    e. 就地休息恢复
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态信息
             * @returns {boolean} 是否处理了受伤状态，true表示已处理，false表示未受伤或已恢复
             */
            handleInjuredState(adventurer) {
                // 判断受伤状态的严重程度
                const isInjured = adventurer.hp < adventurer.maxHp * 0.3; // 轻伤（生命值<30%）
                const isSeverelyInjured = adventurer.hp < adventurer.maxHp * 0.15; // 重伤（生命值<15%）
                
                // 增加安全检查，防止冒险者卡在受伤状态
                // 如果未受伤或已经在休息状态，则检查是否已恢复到安全水平
                if (!isInjured || adventurer.state === 'emergency_rest' || adventurer.state === 'field_rest') {
                    // 如果已经恢复到安全水平（生命值≥30%），重置状态
                    if (adventurer.hp >= adventurer.maxHp * 0.3) {
                        adventurer.state = 'idle'; // 重置为闲置状态
                        adventurer.restStartTime = null; // 清除休息开始时间
                    }
                    return false; // 未受伤或已恢复，返回false
                }
                
                // 记录受伤状态并采用保守策略
                adventurer.log.push(`${new Date().toLocaleTimeString()} 处于受伤状态（HP: ${Math.floor(adventurer.hp)}/${adventurer.maxHp}），采用保守策略`);
                
                // 1. 重伤时立即寻求治疗，不考虑其他行为
                // 当生命值极低时，优先级最高，必须立即治疗
                if (isSeverelyInjured) {
                    // 尝试寻求医疗治疗
                    if (this.seekMedicalTreatment(adventurer)) {
                        return true; // 成功开始治疗，返回true
                    }
                    // 如果无法治疗（如找不到治疗点或金币不足），就地休息
                    this.startEmergencyRest(adventurer);
                    return true; // 已处理重伤状态，返回true
                }
                
                // 2. 轻度受伤时的优先级处理
                // 饥饿优先级提高 - 受伤时更需要食物恢复
                // 受伤状态下对饥饿的容忍度降低，需要更频繁地进食
                if (adventurer.hunger <= Config.HUNGER_CRITICAL * 1.5) {
                    // 寻找最近的饭店进行营养恢复
                    const restaurant = this.findNearestBuilding('饭店', adventurer);
                    const foodCost = Config.BUILDING_FUNCTIONS['饭店'].cost;
                    // 确保找到饭店且有足够的金币支付费用
                    if (restaurant && adventurer.gold >= foodCost) {
                        adventurer.target = restaurant; // 设置目标为饭店
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.treatmentType = 'food'; // 标记为治疗性进食
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤状态下饥饿值低，前往饭店进行营养恢复（费用${foodCost * 2}金）`);
                        return true; // 已处理进食需求，返回true
                    } else if (restaurant && adventurer.gold < foodCost) {
                        // 金币不足但找到了饭店，尝试寻找应急食物
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤且饥饿但金币不足，尝试寻找应急食物`);
                        this.tryEmergencyFood(adventurer);
                        return true; // 已处理进食需求，返回true
                    }
                }
                
                // 优先修理装备（避免装备损坏导致更大伤害）
                // 受伤状态下装备的保护作用更加重要，需要保持良好状态
                if (this.shouldRepairEquipment(adventurer)) {
                    // 尝试自动修理装备
                    if (this.autoRepairEquipment(adventurer)) {
                        return true; // 成功开始修理装备，返回true
                    }
                }
                
                // 尝试寻求医疗治疗以恢复生命值
                if (this.seekMedicalTreatment(adventurer)) {
                    return true; // 成功开始治疗，返回true
                }
                
                // 受伤时可以进行低风险战斗（适度放宽安全门槛）
                // 在确保安全的前提下，通过战斗获得经验和战利品
                if (this.monsters.length > 0 && adventurer.hp > adventurer.maxHp * 0.2 && adventurer.hunger > Config.HUNGER_CRITICAL) {
                    // 寻找适合受伤状态的安全怪物
                    const safeMonster = this.findSafeMonsterForInjured(adventurer);
                    if (safeMonster) {
                        adventurer.target = safeMonster; // 设置目标为安全怪物
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.combatStrategy = '保守型'; // 设置战斗策略为保守型
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤状态下谨慎战斗：${safeMonster.rank}${safeMonster.type}`);
                        return true; // 已开始前往战斗，返回true
                    }
                }
                
                // 如果生命值过低且无法找到治疗或战斗目标，尝试就地休息恢复
                if (adventurer.hp < adventurer.maxHp * 0.1) {
                    this.startEmergencyRest(adventurer); // 启动紧急休息
                    return true; // 已处理紧急休息，返回true
                }
                
                // 无法进行战斗时就地休息恢复
                // 这是受伤状态下的基础恢复行为
                this.startFieldRest(adventurer);
                return true; // 已处理休息行为，返回true
            }
            
            /**
             * 处理正常状态下的优先级决策
             * 当冒险者处于正常健康状态时，按照日常活动优先级进行决策
             * 这是冒险者AI决策系统的核心方法，负责处理大部分日常行为
             * 
             * 正常状态下的行为优先级：
             * 1. 装备修理（高优先级，确保战斗力）
             * 2. 及时进食（中高优先级，维持基础状态）
             * 3. 生命值恢复（中优先级，保持战斗能力）
             * 4. 战斗狩猎（主要行为，获取经验和战利品）
             * 5. 购物消费（低优先级，提升装备水平）
             * 6. 随机游荡（保底行为，维持游戏动态性）
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态信息
             */
            handleNormalStatePriorities(adventurer) {
                // 1. 检查是否需要修理装备（根据装备重要性和耐久度判断）
                // 装备耐久度过低会严重影响战斗力，需要优先处理
                if (this.shouldRepairEquipment(adventurer)) {
                    // 尝试自动修理装备
                    if (this.autoRepairEquipment(adventurer)) {
                        return; // 成功开始修理装备，返回不执行后续逻辑
                    }
                }
                
                // 2. 饥饿值优先级提高 - 在正常状态下也要及时进食
                // 即使在正常状态下，也需要维持良好的饥饿值以避免进入危险状态
                if (adventurer.hunger <= Config.HUNGER_CRITICAL * 1.2) {
                    // 寻找最近的饭店进行进食
                    const restaurant = this.findNearestBuilding('饭店', adventurer);
                    const foodCost = Config.BUILDING_FUNCTIONS['饭店'].cost;
                    // 根据不同情况采取相应行动
                    if (restaurant && adventurer.gold >= foodCost) {
                        // 找到饭店且金币充足
                        adventurer.target = restaurant; // 设置目标为饭店
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 饥饿值偏低，及时前往饭店吃饭（费用${foodCost}金）`);
                        return; // 执行完进食行为后返回
                    } else if (restaurant && adventurer.gold < foodCost) {
                        // 找到饭店但金币不足
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 饥饿但金币不足，尝试寻找其他食物来源`);
                        this.tryEmergencyFood(adventurer); // 尝试寻找应急食物
                        return; // 执行完应急食物寻找后返回
                    } else if (!restaurant) {
                        // 未找到饭店
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 饥饿但未找到饭店，尝试寻找野生食物`);
                        this.tryEmergencyFood(adventurer); // 尝试寻找野生食物
                        return; // 执行完野生食物寻找后返回
                    }
                }
                
                // 3. 生命值低于30%时优先休息（降低门槛）
                // 当生命值较低时，优先恢复以保持战斗能力
                if (adventurer.hp < adventurer.maxHp * 0.3) {
                    // 寻找最近的旅馆进行休息恢复
                    const inn = this.findNearestBuilding('旅馆', adventurer);
                    // 确保找到旅馆且有足够的金币支付费用
                    if (inn && adventurer.gold >= 10) {
                        adventurer.target = inn; // 设置目标为旅馆
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 生命值低，前往旅馆休息`);
                        return; // 执行完休息行为后返回
                    }
                }
                
                // 4. 智能战斗目标选择（主要行为）- 降低安全门槛，让冒险者更积极
                // 战斗是冒险者获取经验和战利品的主要方式，是核心行为
                if (this.monsters.length > 0 && adventurer.hp > adventurer.maxHp * 0.2 && adventurer.hunger > Config.HUNGER_CRITICAL * 0.5) {
                    // 寻找合适的怪物进行战斗
                    const suitableMonster = this.findSuitableMonster(adventurer);
                    if (suitableMonster) {
                        adventurer.target = suitableMonster; // 设置目标为合适怪物
                        adventurer.state = 'moving'; // 改变状态为移动
                        // 根据冒险者和怪物的情况确定战斗策略
                        adventurer.combatStrategy = this.determineCombatStrategy(adventurer, suitableMonster);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 发现${suitableMonster.attribute}${suitableMonster.rank}${suitableMonster.type}，采用${adventurer.combatStrategy}策略`);
                        return; // 执行完战斗行为后返回
                    }
                }
                
                // 如果没有发现合适的怪物，记录原因并尝试探索
                // 当有怪物但找不到合适目标时，主动探索寻找更好的机会
                if (this.monsters.length > 0 && adventurer.hp > adventurer.maxHp * 0.4) {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 地图上有${this.monsters.length}只怪物，但没有找到合适的目标，准备探索`);
                    this.startExplorationWander(adventurer); // 开始探索式游荡
                    return; // 执行完探索行为后返回
                }
                
                // 5. 其他选择（购物、附魔、升级、游荡等）
                // 当没有紧急需求时，可以进行购物、附魔、升级等消费行为
                if (adventurer.gold >= 50 && Math.random() < 0.3) {
                    // 优先考虑附魔 - 如果有低耐久度的高品质装备
                    const equipToEnchant = this.findEquipmentToEnchant(adventurer);
                    if (equipToEnchant) {
                        const magicTower = this.findNearestBuilding('魔法塔', adventurer);
                        if (magicTower) {
                            adventurer.target = magicTower; // 设置目标为魔法塔
                            adventurer.state = 'moving'; // 改变状态为移动
                            adventurer.enchantTarget = equipToEnchant; // 设置附魔目标
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 前往魔法塔为${equipToEnchant.name}附魔`);
                            return; // 执行完附魔行为后返回
                        }
                    }
                    
                    // 考虑装备升级 - 如果有更好装备
                    if (this.canUpgradeEquipment(adventurer)) {
                        const blacksmith = this.findNearestBuilding('铁匠铺', adventurer);
                        if (blacksmith) {
                            adventurer.target = blacksmith; // 设置目标为铁匠铺
                            adventurer.state = 'moving'; // 改变状态为移动
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 前往铁匠铺升级装备`);
                            return; // 执行完升级行为后返回
                        }
                    }
                    
                    // 寻找最近的商店（武器店或防具店）
                    const shop = this.findNearestBuilding('武器店', adventurer) || this.findNearestBuilding('防具店', adventurer);
                    if (shop) {
                        adventurer.target = shop; // 设置目标为商店
                        adventurer.state = 'moving'; // 改变状态为移动
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 闲时前往商店看看`);
                        return; // 执行完购物行为后返回
                    }
                    
                    // 考虑使用炼金术师 - 如果生命值或魔法值较低
                    if ((adventurer.hp < adventurer.maxHp * 0.7 || adventurer.mana < adventurer.maxMana * 0.7) && adventurer.gold >= 30) {
                        const alchemyShop = this.findNearestBuilding('炼金术师', adventurer);
                        if (alchemyShop) {
                            adventurer.target = alchemyShop; // 设置目标为炼金术师
                            adventurer.state = 'moving'; // 改变状态为移动
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 前往炼金术师制作药水`);
                            return; // 执行完炼金术行为后返回
                        }
                    }
                }
                
                // 最后选择：随机游荡 - 使用改进的分散式目标选择
                // 当没有其他明确行为时，进行随机游荡以维持游戏动态性
                const scatteredPos = this.generateScatteredPosition(this.gameAreaWidth, this.gameAreaHeight, 50);
                const targetX = scatteredPos.x;
                const targetY = scatteredPos.y;
                
                adventurer.targetX = targetX; // 设置游荡目标X坐标
                adventurer.targetY = targetY; // 设置游荡目标Y坐标
                adventurer.state = 'wandering'; // 改变状态为游荡
                adventurer.log.push(`${new Date().toLocaleTimeString()} 开始游荡探索`);
            }
            
            /**
             * 寻找需要附魔的装备
             * 优先选择高品质且未附魔的装备进行附魔
             * 
             * 选择标准：
             * 1. 装备稀有度 - 优先选择蓝色及以上稀有度装备
             * 2. 装备价值 - 选择价值较高的装备
             * 3. 附魔状态 - 优先选择未附魔的装备
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {Object|null} 需要附魔的装备或null
             */
            findEquipmentToEnchant(adventurer) {
                // 检查背包中是否有装备
                if (!adventurer.inventory || adventurer.inventory.length === 0) {
                    return null;
                }
                
                let bestEquipment = null;
                let bestValue = 0;
                
                // 遍历背包中的所有装备
                for (let i = 0; i < adventurer.inventory.length; i++) {
                    const equipment = adventurer.inventory[i];
                    
                    // 检查是否为装备且未附魔
                    if (equipment && equipment.slot && !equipment.isEnchanted) {
                        // 计算装备的附魔价值 - 基于稀有度和价值
                        let enchantValue = equipment.value;
                        
                        // 根据稀有度调整附魔优先级
                        const rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(equipment.rarity);
                        if (rarityIndex >= 3) { // 蓝色及以上稀有度
                            enchantValue *= (rarityIndex + 1); // 稀有度越高，优先级越高
                            
                            // 如果找到更高价值的装备，更新最佳选择
                            if (enchantValue > bestValue) {
                                bestValue = enchantValue;
                                bestEquipment = equipment;
                            }
                        }
                    }
                }
                
                return bestEquipment;
            }

            /**
             * 开始探索式游荡，主动寻找怪物
             * 当冒险者没有明确目标时，通过探索式游荡来寻找新的机会
             * 这种游荡方式具有明确的目标导向性，不同于随机游荡
             * 
             * 探索策略：
             * 1. 有怪物时 - 向怪物集中区域移动，提高发现目标的概率
             * 2. 无怪物时 - 随机探索，维持游戏的动态性
             * 3. 目标位置约束 - 确保目标在地图有效范围内
             * 
             * @param {Object} adventurer - 冒险者对象，包含所有属性和状态信息
             */
            startExplorationWander(adventurer) {
                // 选择一个新的探索目标位置，优先考虑怪物可能在的区域
                // 这种目标选择方式比完全随机更有效率
                let targetX, targetY;
                
                // 判断是否有怪物存在
                if (this.monsters.length > 0) {
                    // 如果有怪物，向怪物集中区域移动以提高发现目标的概率
                    // 随机选择一个怪物作为参考点
                    const randomMonster = this.monsters[Math.floor(Math.random() * this.monsters.length)];
                    // 在怪物附近200像素范围内随机选择一个位置作为目标
                    // 这样既能接近怪物区域，又不会直接走向特定怪物
                    targetX = randomMonster.x + (Math.random() - 0.5) * 400;
                    targetY = randomMonster.y + (Math.random() - 0.5) * 400;
                } else {
                    // 没有怪物时随机探索 - 使用改进的分散式目标选择
                    // 确保冒险者在地图上均匀分布，避免聚集
                    const scatteredPos = this.generateScatteredPosition(this.gameAreaWidth, this.gameAreaHeight, 50);
                    targetX = scatteredPos.x;
                    targetY = scatteredPos.y;
                }
                
                // 确保目标位置在地图范围内，避免冒险者走出地图边界
                // 保留50像素的边距，确保目标位置不会太靠近边缘
                targetX = Math.max(50, Math.min(this.gameAreaWidth - 50, targetX));
                targetY = Math.max(50, Math.min(this.gameAreaHeight - 50, targetY));
                
                // 设置游荡目标和状态
                adventurer.targetX = targetX; // 设置游荡目标X坐标
                adventurer.targetY = targetY; // 设置游荡目标Y坐标
                adventurer.state = 'wandering'; // 改变状态为游荡
                // 记录探索行为，包括目标位置信息
                adventurer.log.push(`${new Date().toLocaleTimeString()} 开始探索式游荡，目标位置(${Math.floor(targetX)}, ${Math.floor(targetY)})`);
            }
            
            /**
             * 为受伤的冒险者寻找安全的怪物
             * 受伤状态下需要选择等级较低且胜率高的怪物，确保战斗安全
             * 这是受伤冒险者进行战斗的特殊筛选机制
             * 
             * 安全怪物筛选标准：
             * 1. 等级限制 - 怪物等级不能比冒险者高太多（≤1级差）
             * 2. 稀有度限制 - 只选择普通怪物，避免精英及以上怪物
             * 3. 胜率要求 - 战斗胜率必须达到70%以上
             * 4. 距离限制 - 距离不能太远（≤200像素），避免远征风险
             * 5. 最优选择 - 在满足条件的怪物中选择胜率最高的
             * 
             * @param {Object} adventurer - 受伤的冒险者对象，包含当前状态信息
             * @returns {Object|null} 安全的怪物对象或null（未找到合适目标）
             */
            findSafeMonsterForInjured(adventurer) {
                // 初始化安全怪物和最佳胜率
                let safeMonster = null;
                let bestWinRate = 0;
                
                // 记录寻找安全目标的过程，便于调试
                this.debugLog(`${adventurer.name} 受伤状态下寻找安全目标（HP: ${Math.floor(adventurer.hp)}/${adventurer.maxHp}）`);
                
                // 遍历所有怪物，寻找符合条件的安全目标
                // 使用for循环替代forEach以提高性能
                for (let index = 0; index < this.monsters.length; index++) {
                    const monster = this.monsters[index];
                    // 计算冒险者与怪物之间的距离
                    const dx = monster.x - adventurer.x;
                    const dy = monster.y - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    // 受伤时只打等级较低的怪物，避免挑战过强的对手
                    const levelDiff = monster.level - adventurer.level;
                    if (levelDiff > 1) {
                        // 等级差过大，跳过该怪物
                        this.debugLog(`  怪物${index}: ${monster.rank}${monster.type} Lv.${monster.level} - 跳过：等级较高 (+${levelDiff})`);
                        continue; // 继续检查下一个怪物
                    }
                    
                    // 不打精英及以上的怪物，只选择普通怪物
                    // 精英及以上怪物风险太高，不适合受伤状态的冒险者
                    if (monster.rank !== '普通') {
                        this.debugLog(`  怪物${index}: ${monster.rank}${monster.type} - 跳过：稀有度太高`);
                        continue; // 继续检查下一个怪物
                    }
                    
                    // 计算胜率，需要非常高的胜率（≥70%）才能确保安全
                    const winRate = this.calculateWinRate(adventurer, monster);
                    if (winRate < 0.7) {
                        // 胜率不足，跳过该怪物
                        this.debugLog(`  怪物${index}: ${monster.rank}${monster.type} - 跳过：胜率不够 (${(winRate * 100).toFixed(1)}% < 70%)`);
                        continue; // 继续检查下一个怪物
                    }
                    
                    // 距离不能太远（受伤时不宜远征，限制在200像素内）
                    // 避免受伤状态下长途跋涉增加风险
                    if (distance > 200) {
                        this.debugLog(`  怪物${index}: ${monster.rank}${monster.type} - 跳过：距离太远 (${Math.floor(distance)})`);
                        continue; // 继续检查下一个怪物
                    }
                    
                    // 在所有符合条件的怪物中，选择胜率最高的作为目标
                    if (winRate > bestWinRate) {
                        bestWinRate = winRate; // 更新最佳胜率
                        safeMonster = monster; // 更新安全怪物
                        this.debugLog(`  怪物${index}: ${monster.rank}${monster.type} - 新的安全目标：胜率 ${(winRate * 100).toFixed(1)}%`);
                    }
                }
                
                // 记录最终选择结果
                if (safeMonster) {
                    this.debugLog(`${adventurer.name} 受伤状态选择安全目标: ${safeMonster.rank}${safeMonster.type}, 胜率: ${(bestWinRate * 100).toFixed(1)}%`);
                } else {
                    this.debugLog(`${adventurer.name} 受伤状态没有找到安全的怪物`);
                }
                
                // 返回找到的安全怪物或null
                return safeMonster;
            }
            
            /**
             * 寻求医疗治疗
             * 当冒险者受伤时，通过寻找合适的治疗点来恢复生命值
             * 采用分级治疗策略，优先选择效果更好的治疗方式
             * 
             * 治疗优先级：
             * 1. 旅馆治疗 - 效果最好，费用较高（20金币）
             * 2. 饭店恢复 - 辅助治疗，费用较低（10金币）
             * 
             * @param {Object} adventurer - 需要治疗的冒险者对象
             * @returns {boolean} 是否成功开始治疗，true表示已开始治疗，false表示无法治疗
             */
            seekMedicalTreatment(adventurer) {
                // 优先选择旅馆治疗（效果好）
                // 旅馆提供最好的治疗效果，但费用较高（20金币）
                const inn = this.findNearestBuilding('旅馆', adventurer);
                if (inn && adventurer.gold >= 20) { // 提高治疗费用，但效果更好
                    adventurer.target = inn; // 设置目标为旅馆
                    adventurer.state = 'moving'; // 改变状态为移动
                    adventurer.treatmentType = 'inn'; // 标记治疗类型为旅馆治疗
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤严重，前往旅馆接受治疗`);
                    return true; // 成功开始旅馆治疗，返回true
                }
                
                // 其次选择饭店恢复（辅助治疗）
                // 饭店提供辅助治疗效果，费用较低（10金币）
                const restaurant = this.findNearestBuilding('饭店', adventurer);
                if (restaurant && adventurer.gold >= 10) {
                    adventurer.target = restaurant; // 设置目标为饭店
                    adventurer.state = 'moving'; // 改变状态为移动
                    adventurer.treatmentType = 'food'; // 标记治疗类型为食物恢复
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤状态下前往饭店恢复体力`);
                    return true; // 成功开始饭店恢复，返回true
                }
                
                // 无法找到合适的治疗点或金币不足，返回false
                return false;
            }
            
            /**
             * 紧急休息（重伤时使用）
             * @param {Object} adventurer - 冒险者对象
             */
            startEmergencyRest(adventurer) {
                adventurer.state = 'emergency_rest';
                adventurer.restStartTime = Date.now();
                adventurer.log.push(`${new Date().toLocaleTimeString()} 重伤无法治疗，开始紧急休息恢复`);
            }
            
            /**
             * 就地休息（轻伤时使用）
             * @param {Object} adventurer - 冒险者对象
             */
            startFieldRest(adventurer) {
                adventurer.state = 'field_rest';
                adventurer.restStartTime = Date.now();
                adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤状态下就地休息恢复`);
            }
            
            /**
             * 检查是否有装备需要紧急修理
             * @param {Object} adventurer - 冒险者对象
             * @returns {boolean} 是否有装备需要紧急修理
             */
            hasEquipmentNeedingUrgentRepair(adventurer) {
                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    // 调整耐久度阈值，使自动修理更加合理
                    // 耐久度低于30才需要紧急修理，给玩家更多缓冲时间
                    if (equipment && equipment.durability < 30) {
                        return true;
                    }
                }
                return false;
            }
            
            /**
             * 检查是否需要修理装备 - 智能装备维护系统
             * 检查冒险者所有装备的耐久度状态，判断是否需要进行修理
             * 根据装备类型、价值、稀有度和重要性采用智能评估机制
             * 支持AI决策系统优化装备维护时机和优先级
             * 
             * 智能评估机制：
             * 1. 综合考虑装备价值、稀有度、类型重要性
             * 2. 动态调整修理阈值基于装备综合评分
             * 3. 高价值装备降低修理阈值提高优先级
             * 4. 低价值装备提高修理阈值避免频繁修理
             * 
             * 评估维度：
             * 1. 耐久度状态：当前耐久度比例
             * 2. 装备价值：影响修理优先级和阈值
             * 3. 装备类型：核心装备优先级更高
             * 4. 稀有度等级：高稀有度装备优先级更高
             * 5. 槽位重要性：武器>防具>饰品
             * 
             * 动态阈值计算：
             * 基础阈值 = 根据装备类型确定(武器防具20%，饰品10%)
             * 价值调整 = 装备价值/1000 (价值越高阈值越低)
             * 稀有度调整 = 稀有度索引*0.01 (稀有度越高阈值越低)
             * 最终阈值 = 基础阈值 - 价值调整 - 稀有度调整
             * 最低阈值 = 5% (防止过度磨损)
             * 
             * 优先级评估：
             * - 高价值装备：阈值降低至10-15%
             * - 高稀有度装备：阈值降低至10-15%
             * - 核心装备(武器/胸甲)：优先级最高
             * - 任何装备耐久度<5%：紧急优先级
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {boolean} 是否有装备需要修理
             */
            shouldRepairEquipment(adventurer) {
                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    if (!equipment) continue;
                    
                    // 计算耐久度比例
                    const durabilityRatio = equipment.durability / equipment.maxDurability;
                    
                    // 获取装备稀有度索引
                    const rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(equipment.rarity);
                    
                    // 根据装备类型确定基础修理阈值
                    let baseThreshold = 0.2; // 武器和防具默认20%
                    if (['戒指', '项链', '腰带', '护符'].includes(equipment.slot)) {
                        baseThreshold = 0.1; // 饰品默认10%
                    }
                    
                    // 根据装备价值和稀有度动态调整阈值
                    const valueAdjustment = Math.min(0.1, equipment.value / 10000); // 价值越高阈值越低
                    const rarityAdjustment = rarityIndex * 0.01; // 稀有度越高阈值越低
                    
                    // 计算最终修理阈值，最低不低于5%
                    const repairThreshold = Math.max(0.05, baseThreshold - valueAdjustment - rarityAdjustment);
                    
                    // 紧急情况：任何装备耐久度低于5%都需要修理
                    if (durabilityRatio < 0.05) {
                        return true;
                    }
                    
                    // 根据动态阈值判断是否需要修理
                    if (durabilityRatio < repairThreshold) {
                        return true;
                    }
                }
                return false;
            }
            
            findSuitableMonster(adventurer) {
                let bestMonster = null;
                let bestScore = -1;
                
                // 先记录当前可用的怪物情况
                this.debugLog(`${adventurer.name} 正在寻找合适的怪物，地图上共有 ${this.monsters.length} 只怪物`);
                
                // 优化：限制最多检查20个怪物以提高性能
                const maxCheckCount = Math.min(20, this.monsters.length);
                for (let i = 0; i < maxCheckCount; i++) {
                    const monster = this.monsters[i];
                    const dx = monster.x - adventurer.x;
                    const dy = monster.y - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    // 计算战斗胜率（降低门槛）
                    const winRate = this.calculateWinRate(adventurer, monster);
                    
                    // 记录每只怪物的评估情况（降低日志频率以提高性能）
                    if (Math.random() < 0.1) { // 只有10%概率记录日志
                        this.debugLog(`怪物${i}: ${monster.rank}${monster.type} Lv.${monster.level}, 距离: ${Math.floor(distance)}, 胜率: ${(winRate * 100).toFixed(1)}%`);
                    }
                    
                    // 进一步降低胜率要求到0.01，让冒险者更积极战斗
                    if (winRate < 0.01) {
                        if (Math.random() < 0.1) { // 只有10%概率记录日志
                            this.debugLog(`  - 跳过：胜率太低 (${(winRate * 100).toFixed(1)}% < 1%)`);
                        }
                        continue;
                    }
                    
                    // 计算收益
                    const profit = this.calculateCombatProfit(adventurer, monster);
                    
                    // 计算综合评分
                    let score = 0;
                    
                    // 等级适合度 - 放宽等级限制，鼓励挑战更强的怪物
                    const levelDiff = Math.abs(monster.level - adventurer.level);
                    if (levelDiff <= 2) score += 120;  // 相近等级给予高分
                    else if (levelDiff <= 5) score += 100 - levelDiff * 8;  // 中等差异仍然可接受
                    else if (levelDiff <= 8) score += 60 - levelDiff * 4;   // 较大差异也给予机会
                    else if (levelDiff <= 12) score += 30 - levelDiff * 1.5; // 很大差异也考虑
                    else score += 15; // 即使等级相差很大也给一些基础分
                    
                    // 胜率加分（提高权重）
                    score += winRate * 80; // 从50提高到80
                    
                    // 收益加分
                    score += profit / 80; // 从100降低到80，降低收益的影响
                    
                    // 稀有度加分
                    switch(monster.rank) {
                        case '精英': score += 15; break;
                        case '首领': score += 30; break;
                        case '传说': score += 45; break;
                        case '神话': score += 60; break;
                        default: score += 10; // 给普通怪物也加一些分
                    }
                    
                    // 距离惩罚（进一步减少惩罚）
                    score -= distance * 0.02; // 从0.05减少到0.02
                    
                    // 职业克制加分
                    score += this.getClassAdvantage(adventurer.class, monster.type) * 15;
                    
                    // 如果是第一次评估或者得分更高，就选择这个怪物
                    if (score > bestScore) {
                        bestScore = score;
                        bestMonster = monster;
                        if (Math.random() < 0.1) { // 只有10%概率记录日志
                            this.debugLog(`  - 新的最佳目标：得分 ${score.toFixed(1)}`);
                        }
                    } else {
                        if (Math.random() < 0.1) { // 只有10%概率记录日志
                            this.debugLog(`  - 评分: ${score.toFixed(1)} (不如当前最佳 ${bestScore.toFixed(1)})`);
                        }
                    }
                }
                
                // 如果没有找到合适的怪物，选择最近的怪物（保底机制）
                if (!bestMonster && this.monsters.length > 0) {
                    this.debugLog(`${adventurer.name} 没有找到高评分怪物，选择最近的怪物作为目标`);
                    let closestMonster = null;
                    let closestDistance = Infinity;
                    
                    // 使用for循环替代forEach以提高性能
                    for (let i = 0; i < this.monsters.length; i++) {
                        const monster = this.monsters[i];
                        const dx = monster.x - adventurer.x;
                        const dy = monster.y - adventurer.y;
                        const distance = Math.sqrt(dx * dx + dy * dy);
                        
                        if (distance < closestDistance) {
                            closestDistance = distance;
                            closestMonster = monster;
                        }
                    }
                    
                    if (closestMonster) {
                        bestMonster = closestMonster;
                        this.debugLog(`${adventurer.name} 保底选择: ${bestMonster.rank}${bestMonster.type} Lv.${bestMonster.level}, 距离: ${Math.floor(closestDistance)}`);
                    }
                }
                
                // 如果仍然没有找到怪物，记录原因
                if (!bestMonster) {
                    this.debugLog(`${adventurer.name} 没有找到合适的怪物。原因可能是：`);
                    this.debugLog(`  - 地图上没有怪物`);
                    this.debugLog(`  - 冒险者位置: (${Math.floor(adventurer.x)}, ${Math.floor(adventurer.y)})`);
                    this.debugLog(`  - 冒险者属性: 攻击${adventurer.attack}, 防御${adventurer.defense}, 生命${adventurer.hp}/${adventurer.maxHp}`);
                } else {
                    this.debugLog(`${adventurer.name} 选择目标: ${bestMonster.rank}${bestMonster.type} Lv.${bestMonster.level}, 最终得分: ${bestScore.toFixed(1)}`);
                }
                
                return bestMonster;
            }
            
            /**
             * 计算战斗胜率 - 战斗系统
             * 基于冒险者和怪物属性计算理论胜率
             * 考虑职业克制和属性克制因素
             * 返回0-1之间的胜率值
             * 
             * 胜率计算流程：
             * 1. 计算冒险者综合战力值
             * 2. 计算怪物综合战力值
             * 3. 处理怪物战力为0的特殊情况
             * 4. 基础胜率 = 冒险者战力/(冒险者战力+怪物战力)
             * 5. 应用职业克制加成(±20%)
             * 6. 应用属性克制加成(±10%)
             * 7. 限制胜率范围在0-1之间
             * 
             * 战力计算：
             * - 攻击力 + 防御力 + 生命值/10
             * - 生命值权重降低避免过度影响
             * - 综合考虑三大基础属性
             * - 简化计算提高性能
             * 
             * 克制系统：
             * - 职业克制：±20%胜率调整
             * - 属性克制：±10%胜率调整
             * - 多重克制效果可叠加
             * - 克制关系配置化管理
             * 
             * 数据处理：
             * - 零值特殊处理避免除零错误
             * - 胜率范围限制防止异常值
             * - 数值标准化便于理解和使用
             * - 计算结果具有预测性
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {Object} monster - 怪物对象
             * @returns {number} 0-1之间的胜率值
             */
            /**
             * 计算战斗胜率 - 战斗评估系统
             * 根据冒险者和怪物的属性计算预期胜率
             * 考虑职业克制和属性克制因素
             * 用于AI决策和战斗风险评估
             * 
             * 胜率计算公式：
             * 1. 冒险者战力 = 攻击力 + 防御力 + 生命值/10
             * 2. 怪物战力 = 攻击力 + 防御力 + 生命值/10
             * 3. 基础胜率 = 冒险者战力 / (冒险者战力 + 怪物战力)
             * 4. 职业克制加成 = 克制值 × 0.2
             * 5. 属性克制加成 = 克制值 × 0.1
             * 6. 最终胜率 = 基础胜率 + 职业克制 + 属性克制
             * 7. 胜率范围限制在0-1之间
             * 
             * 战力计算特点：
             * - 攻击力和防御力直接计入战力
             * - 生命值权重降低(除以10)避免过度影响
             * - 综合考虑攻防血三大核心属性
             * - 数值标准化便于比较
             * 
             * 克制系统加成：
             * - 职业克制权重较高(0.2倍)
             * - 属性克制权重中等(0.1倍)
             * - 克制值可正可负影响胜率
             * - 多重克制效果可叠加
             * 
             * 胜率限制机制：
             * - 最小值0避免负胜率
             * - 最大值1避免超胜率
             * - 使用Math.max和Math.min确保范围
             * - 保持计算结果合理性
             * 
             * 应用场景：
             * - 冒险者AI战斗决策
             * - 怪物AI威胁评估
             * - 战斗推荐系统
             * - 风险收益分析
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {Object} monster - 怪物对象
             * @returns {number} 预期胜率(0-1之间)
             */
            calculateWinRate(adventurer, monster) {
                const advPower = adventurer.attack + adventurer.defense + adventurer.hp / 10;
                const monPower = monster.attack + monster.defense + monster.hp / 10;
                
                if (monPower === 0) return 1;
                
                let winRate = advPower / (advPower + monPower);
                
                // 考虑职业克制
                const advantage = this.getClassAdvantage(adventurer.class, monster.type);
                winRate += advantage * 0.2;
                
                // 考虑属性克制
                winRate += this.getAttributeAdvantage(adventurer, monster) * 0.1;
                
                return Math.max(0, Math.min(1, winRate));
            }
            
            /**
             * 计算战斗收益 - 经济系统
             * 评估与特定怪物战斗的预期收益
             * 考虑奖励、掉落和战斗成本
             * 返回净收益值用于AI决策
             * 
             * 收益计算流程：
             * 1. 计算基础收益(金币+经验)
             * 2. 评估装备掉落的潜在价值
             * 3. 估算战斗消耗成本
             * 4. 返回净收益值(收益-成本)
             * 
             * 收益构成：
             * - 金币奖励：怪物固定金币奖励
             * - 经验奖励：怪物固定经验奖励
             * - 装备掉落：掉落率×装备等级×50
             * - 总收益为各项之和
             * 
             * 成本估算：
             * - 等级成本：怪物等级×5
             * - 战斗时长：生命值/攻击力×2
             * - 装备损耗：间接体现在成本中
             * - 药品消耗：间接体现在成本中
             * 
             * 决策支持：
             * - 为冒险者AI提供战斗选择依据
             * - 收益为负时避免战斗
             * - 收益越高优先级越高
             * - 支持自动战斗决策系统
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {Object} monster - 怪物对象
             * @returns {number} 战斗净收益值
             */
            /**
             * 计算战斗收益 - 经济系统
             * 评估与特定怪物战斗的预期收益
             * 考虑奖励、掉落和战斗成本
             * 返回净收益值用于AI决策
             * 
             * 收益计算流程：
             * 1. 计算基础收益(金币+经验)
             * 2. 评估装备掉落的潜在价值
             * 3. 估算战斗消耗成本
             * 4. 返回净收益值(收益-成本)
             * 
             * 收益构成：
             * - 金币奖励：怪物固定金币奖励
             * - 经验奖励：怪物固定经验奖励
             * - 装备掉落：掉落率×装备等级×50
             * - 总收益为各项之和
             * 
             * 成本估算：
             * - 等级成本：怪物等级×5
             * - 战斗时长：生命值/攻击力×2
             * - 综合考虑装备损耗和药品消耗
             * - 成本随怪物强度增加
             * 
             * 计算公式：
             * 基础收益 = 金币奖励 + 经验奖励
             * 掉落价值 = 掉落率 × 装备等级 × 50
             * 战斗成本 = 怪物等级 × 5 + (怪物生命值 ÷ 冒险者攻击力) × 2
             * 净收益 = 基础收益 + 掉落价值 - 战斗成本
             * 
             * 设计考虑：
             * - 平衡收益与风险
             * - 考虑长期收益价值
             * - 支持AI决策制定
             * - 避免收益过高破坏平衡
             * 
             * 应用场景：
             * - 冒险者AI目标选择
             * - 怪物威胁等级评估
             * - 战斗策略优化
             * - 资源分配决策
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {Object} monster - 怪物对象
             * @returns {number} 战斗净收益值
             */
            calculateCombatProfit(adventurer, monster) {
                let profit = monster.rewardGold + monster.rewardExp;
                
                // 考虑掉落概率
                profit += monster.dropRate * monster.equipmentDropLevel * 50;
                
                // 考虑战斗成本（装备损耗、药品消耗等）
                const combatCost = monster.level * 5 + (monster.hp / adventurer.attack) * 2;
                
                return profit - combatCost;
            }
            
            /**
             * 获取职业克制优势 - 战斗系统
             * 根据冒险者职业和怪物类型查询克制关系
             * 返回克制数值用于胜率和评分计算
             * 支持正向克制(优势)和负向克制(劣势)
             * 
             * 克制关系配置：
             * - 战士：克制哥布林(+30%)、兽人(+20%)，被元素生物克制(-20%)
             * - 法师：克制骷髅(+40%)、僵尸(+30%)，被龙类克制(-30%)
             * - 弓箭手：克制飞行单位(+50%)、蝙蝠(+40%)，被巨魔克制(-20%)
             * - 盗贼：克制幽灵(+40%)、法师(+30%)，被战士克制(-10%)
             * - 牧师：克制恶魔(+50%)、不死生物(+40%)，被物理系克制(-20%)
             * 
             * 克制数值：
             * - 正值表示优势：+0.2表示20%胜率加成
             * - 负值表示劣势：-0.3表示30%胜率减成
             * - 零值表示无克制关系
             * - 数值范围通常在-0.5到+0.5之间
             * 
             * 数据结构：
             * - 使用嵌套对象存储克制关系
             * - 外层键为冒险者职业
             * - 内层键为怪物类型
             * - 值为克制数值
             * 
             * 查询机制：
             * - 安全访问避免未定义错误
             * - 未配置关系默认返回0
             * - 支持动态扩展克制关系
             * - 查询性能高效O(1)
             * 
             * @param {string} adventurerClass - 冒险者职业
             * @param {string} monsterType - 怪物类型
             * @returns {number} 克制数值(-0.5到+0.5)
             */
            /**
             * 获取职业克制优势 - 战斗系统
             * 根据冒险者职业和怪物类型查询克制关系
             * 返回克制数值用于胜率和评分计算
             * 支持正向克制(优势)和负向克制(劣势)
             * 
             * 克制关系配置：
             * - 战士：克制哥布林(+30%)、兽人(+20%)，被元素生物克制(-20%)
             * - 法师：克制骷髅(+40%)、僵尸(+30%)，被龙类克制(-30%)
             * - 弓箭手：克制飞行单位(+50%)、蝙蝠(+40%)，被巨魔克制(-20%)
             * - 盗贼：克制幽灵(+40%)、法师(+30%)，被战士克制(-10%)
             * - 牧师：克制恶魔(+50%)、不死生物(+40%)，被物理系克制(-20%)
             * 
             * 克制数值：
             * - 正值表示优势：+0.2表示20%胜率加成
             * - 负值表示劣势：-0.3表示30%胜率减成
             * - 零值表示无克制关系
             * - 数值范围通常在-0.5到+0.5之间
             * 
             * 数据结构：
             * - 使用嵌套对象存储克制关系
             * - 外层键为冒险者职业
             * - 内层键为怪物类型
             * - 值为克制数值
             * 
             * 查询机制：
             * - 安全访问避免未定义错误
             * - 未配置关系默认返回0
             * - 支持动态扩展克制关系
             * - 查询性能高效O(1)
             * 
             * 应用场景：
             * - 战斗胜率计算
             * - 怪物威胁评估
             * - 冒险者目标选择
             * - 战斗策略制定
             * 
             * @param {string} adventurerClass - 冒险者职业
             * @param {string} monsterType - 怪物类型
             * @returns {number} 克制数值(-0.5到+0.5)
             */
            getClassAdvantage(adventurerClass, monsterType) {
                const advantages = {
                    '战士': { '哥布林': 0.3, '兽人': 0.2, '骷髅': -0.1, '元素生物': -0.2 },
                    '法师': { '骷髅': 0.4, '僵尸': 0.3, '元素生物': 0.2, '龙类': -0.3 },
                    '弓箭手': { '蜘蛛': 0.3, '蝙蝠': 0.4, '飞行': 0.5, '巨魔': -0.2 },
                    '盗贼': { '幽灵': 0.4, '法师': 0.3, '弓箭手': 0.2, '战士': -0.1 },
                    '牧师': { '恶魔': 0.5, '不死': 0.4, '诅咒': 0.3, '物理': -0.2 }
                };
                
                return advantages[adventurerClass]?.[monsterType] || 0;
            }
            
            /**
             * 获取属性克制优势 - 战斗系统
             * 根据冒险者主属性和怪物属性查询克制关系
             * 返回属性克制数值用于胜率计算
             * 实现五行相克和光暗对立系统
             * 
             * 克制关系配置：
             * - 火克土(+20%)，被水克(-20%)
             * - 水克火(+20%)，被土克(-20%)
             * - 土克风(+20%)，被火克(-20%)
             * - 风克水(+20%)，被土克(-20%)
             * - 光克暗(+30%)，暗克光(+30%)
             * - 无克制关系返回0
             * 
             * 属性映射：
             * - 通过getAdventurerMainAttribute获取冒险者主属性
             * - 直接使用monster.attribute获取怪物属性
             * - 职业与属性的对应关系固定
             * - 支持扩展新的属性类型
             * 
             * 克制数值：
             * - 正值表示优势：+0.2表示20%胜率加成
             * - 负值表示劣势：-0.2表示20%胜率减成
             * - 零值表示无克制：无胜率影响
             * - 光暗相互克制数值更高
             * 
             * 数据结构：
             * - 使用嵌套对象存储克制关系
             * - 外层键为攻击方属性
             * - 内层键为被攻击方属性
             * - 值为克制数值
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {Object} monster - 怪物对象
             * @returns {number} 属性克制数值
             */
            /**
             * 获取属性克制优势 - 战斗系统
             * 根据冒险者主属性和怪物属性查询克制关系
             * 返回属性克制数值用于胜率计算
             * 实现五行相克和光暗对立系统
             * 
             * 克制关系配置：
             * - 火克土(+20%)，被水克(-20%)
             * - 水克火(+20%)，被土克(-20%)
             * - 土克风(+20%)，被火克(-20%)
             * - 风克水(+20%)，被土克(-20%)
             * - 光克暗(+30%)，暗克光(+30%)
             * - 无克制关系返回0
             * 
             * 属性映射：
             * - 通过getAdventurerMainAttribute获取冒险者主属性
             * - 直接使用monster.attribute获取怪物属性
             * - 职业与属性的对应关系固定
             * - 支持扩展新的属性类型
             * 
             * 克制数值：
             * - 正值表示优势：+0.2表示20%胜率加成
             * - 负值表示劣势：-0.2表示20%胜率减成
             * - 零值表示无克制：无胜率影响
             * - 光暗相互克制数值更高
             * 
             * 数据结构：
             * - 使用嵌套对象存储克制关系
             * - 外层键为攻击方属性
             * - 内层键为被攻击方属性
             * - 值为克制数值
             * 
             * 相克循环：
             * - 火→土→风→水→火（循环相克）
             * - 光↔暗（相互克制）
             * - 保持平衡避免某属性过强
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {Object} monster - 怪物对象
             * @returns {number} 属性克制数值
             */
            getAttributeAdvantage(adventurer, monster) {
                // 简化的属性克制系统
                const adventurerAttr = this.getAdventurerMainAttribute(adventurer);
                const monsterAttr = monster.attribute;
                
                const restraint = {
                    '火': { '土': 0.2, '水': -0.2 },
                    '水': { '火': 0.2, '土': -0.2 },
                    '土': { '风': 0.2, '火': -0.2 },
                    '风': { '水': 0.2, '土': -0.2 },
                    '光': { '暗': 0.3 },
                    '暗': { '光': 0.3 }
                };
                
                return restraint[adventurerAttr]?.[monsterAttr] || 0;
            }
            
            /**
             * 获取冒险者主属性 - 属性系统
             * 根据冒险者职业确定其主属性类型
             * 用于属性克制关系计算
             * 支持五行和光暗属性体系
             * 
             * 职业属性映射：
             * - 战士 → 土属性：防御型，克制风属性
             * - 法师 → 火属性：攻击型，克制土属性
             * - 弓箭手 → 风属性：敏捷型，克制水属性
             * - 盗贼 → 暗属性：隐匿型，克制光属性
             * - 牧师 → 光属性：治疗型，克制暗属性
             * 
             * 属性体系：
             * - 五行属性：火、水、土、风
             * - 特殊属性：光、暗
             * - 相克循环：火→土→风→水→火
             * - 光暗对立：相互克制
             * 
             * 默认处理：
             * - 未定义职业返回'普通'属性
             * - 普通属性无特殊克制关系
             * - 保证方法调用安全性
             * - 支持扩展新的职业类型
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {string} 主属性名称
             */
            /**
             * 获取冒险者主属性 - 属性系统
             * 根据冒险者职业确定其主属性类型
             * 用于属性克制关系计算
             * 支持五行和光暗属性体系
             * 
             * 职业属性映射：
             * - 战士 → 土属性：防御型，克制风属性
             * - 法师 → 火属性：攻击型，克制土属性
             * - 弓箭手 → 风属性：敏捷型，克制水属性
             * - 盗贼 → 暗属性：隐匿型，克制光属性
             * - 牧师 → 光属性：治疗型，克制暗属性
             * 
             * 属性体系：
             * - 五行属性：火、水、土、风
             * - 特殊属性：光、暗
             * - 相克循环：火→土→风→水→火
             * - 光暗对立：相互克制
             * 
             * 默认处理：
             * - 未定义职业返回'普通'属性
             * - 普通属性无特殊克制关系
             * - 保证方法调用安全性
             * - 支持扩展新的职业类型
             * 
             * 设计优势：
             * - 职业与属性强关联
             * - 属性克制关系清晰
             * - 系统平衡性良好
             * - 易于理解和记忆
             * 
             * @param {Object} adventurer - 冒险者对象
             * @returns {string} 主属性名称
             */
            getAdventurerMainAttribute(adventurer) {
                // 根据职业决定主属性
                const classAttr = {
                    '战士': '土',
                    '法师': '火',
                    '弓箭手': '风',
                    '盗贼': '暗',
                    '牧师': '光'
                };
                
                return classAttr[adventurer.class] || '普通';
            }
            
            /**
             * 冒险者使用技能
             * @param {Object} adventurer - 冒险者对象
             * @returns {Object} 技能使用结果
             */
            useAdventurerSkill(adventurer) {
                // 检查MP是否足够
                if (adventurer.mp < 20) {
                    return { used: false };
                }
                
                // 消耗MP
                adventurer.mp -= 20;
                
                // 根据职业选择技能
                const className = adventurer.class;
                const skills = Config.CLASSES[className].skills;
                const skillName = skills[Math.floor(Math.random() * skills.length)];
                
                // 计算技能伤害
                let damage = 0;
                let damageMultiplier = 1.0;
                let isAoE = false; // 是否为群体攻击
                let targets = [adventurer.target]; // 默认只有一个目标
                
                switch(className) {
                    case '战士':
                        // 战士技能：有一定几率使用群体攻击
                        if (Math.random() < 0.3) {
                            // 群体攻击技能
                            isAoE = true;
                            targets = this.findNearbyMonsters(adventurer, 80, 3);
                            damageMultiplier = 1.5 + Math.random() * 0.5; // 群体攻击伤害较低
                        } else {
                            // 单体高伤害技能
                            damageMultiplier = 2.0 + Math.random() * 1.0;
                        }
                        break;
                    case '法师':
                        // 法师技能：高几率群体攻击
                        if (Math.random() < 0.6) {
                            isAoE = true;
                            targets = this.findNearbyMonsters(adventurer, 100, 5);
                            damageMultiplier = 1.8 + Math.random() * 0.7;
                        } else {
                            damageMultiplier = 1.8 + Math.random() * 1.2;
                        }
                        break;
                    case '弓箭手':
                        // 弓箭手技能：中等几率群体攻击
                        if (Math.random() < 0.4) {
                            isAoE = true;
                            targets = this.findNearbyMonsters(adventurer, 90, 4);
                            damageMultiplier = 1.5 + Math.random() * 0.6;
                        } else {
                            damageMultiplier = 1.5 + Math.random() * 0.8;
                        }
                        break;
                    case '盗贼':
                        // 盗贼技能：单体高暴击技能
                        damageMultiplier = 1.6 + Math.random() * 1.0;
                        // 增加暴击率
                        if (Math.random() < 0.5) {
                            damageMultiplier *= 1.5; // 额外暴击加成
                        }
                        break;
                    case '牧师':
                        // 牧师技能：治疗自己并造成伤害
                        const healAmount = Math.min(adventurer.maxHp - adventurer.hp, 30 + Math.random() * 20);
                        adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + healAmount);
                        damageMultiplier = 1.2 + Math.random() * 0.6;
                        break;
                }
                
                // 计算最终伤害 - 提高技能伤害以增强战斗体验
                const researchAttackBonus = this.researchEffects.attackBonus || 0;
                const finalAttack = adventurer.attack * (1 + researchAttackBonus);
                damage = Math.max(8, finalAttack * damageMultiplier - adventurer.target.defense * 0.15); // 提高基础伤害，降低防御减免
                
                // 记录技能冷却 - 减少冷却时间以提高技能使用频率
                const cooldownTime = isAoE ? 6000 : 3000; // 群体攻击冷却时间更长，但整体减少
                adventurer.skillCooldowns[skillName] = Date.now() + cooldownTime;
                
                return {
                    used: true,
                    skillName: skillName,
                    damage: damage,
                    isAoE: isAoE,
                    targets: targets
                };
            }
            
            determineCombatStrategy(adventurer, monster) {
                const hpRatio = adventurer.hp / adventurer.maxHp;
                const levelDiff = monster.level - adventurer.level;
                const winRate = this.calculateWinRate(adventurer, monster);
                
                if (winRate > 0.8) return '攻击性';
                if (winRate > 0.6) return '平衡型';
                if (winRate > 0.4) return '谨慎型';
                if (hpRatio < 0.5) return '防御型';
                
                return '逃跑';
            }
            
            handleIdleBehavior(adventurer) {
                const behaviors = [];
                
                // 检查是否可以购物
                if (adventurer.gold > 100) {
                    const shop = this.findNearestBuilding('武器店', adventurer) || this.findNearestBuilding('防具店', adventurer);
                    if (shop) {
                        behaviors.push({
                            action: 'shopping',
                            target: shop,
                            priority: 30
                        });
                    }
                }
                
                // 检查是否可以升级装备
                if (this.canUpgradeEquipment(adventurer)) {
                    behaviors.push({
                        action: 'upgrade',
                        priority: 60
                    });
                }
                
                // 检查是否可以交易
                if (this.canTradeWithOthers(adventurer)) {
                    behaviors.push({
                        action: 'trade',
                        priority: 40
                    });
                }
                
                // 无所事事时随机游荡
                if (behaviors.length === 0) {
                    behaviors.push({
                        action: 'wander',
                        priority: 10
                    });
                }
                
                // 选择最高优先级的行为
                behaviors.sort((a, b) => b.priority - a.priority);
                this.executeIdleBehavior(adventurer, behaviors[0]);
            }
            
            canUpgradeEquipment(adventurer) {
                return adventurer.inventory.some(item => {
                    const currentEquip = adventurer.equipment[item.slot];
                    return !currentEquip || this.calculateItemScore(item) > this.calculateItemScore(currentEquip) * 1.1;
                });
            }
            
            canTradeWithOthers(adventurer) {
                return adventurer.inventory.length > 5 && 
                       this.adventurers.some(other => 
                           other.id !== adventurer.id && 
                           other.state !== 'dead' &&
                           this.canBenefitFromTrade(adventurer, other)
                       );
            }
            
            canBenefitFromTrade(adventurer1, adventurer2) {
                // 简化的交易逻辑：检查是否有互补装备
                return adventurer1.inventory.some(item1 => 
                    adventurer2.inventory.some(item2 => 
                        item1.slot === item2.slot && 
                        this.wouldBenefitFromSwap(adventurer1, adventurer2, item1, item2)
                    )
                );
            }
            
            wouldBenefitFromSwap(adv1, adv2, item1, item2) {
                const score1For1 = this.calculateItemScoreForAdventurer(item1, adv1);
                const score1For2 = this.calculateItemScoreForAdventurer(item1, adv2);
                const score2For1 = this.calculateItemScoreForAdventurer(item2, adv1);
                const score2For2 = this.calculateItemScoreForAdventurer(item2, adv2);
                
                return (score2For1 + score1For2) > (score1For1 + score2For2) * 1.1;
            }
            
            calculateItemScoreForAdventurer(item, adventurer) {
                let score = this.calculateItemScore(item);
                
                // 根据职业调整评分
                const classBonus = this.getClassEquipmentBonus(adventurer.class, item);
                score *= (1 + classBonus);
                
                return score;
            }
            
            getClassEquipmentBonus(adventurerClass, item) {
                const bonuses = {
                    '战士': { '武器': 0.2, '胸甲': 0.15, '防御': 0.1 },
                    '法师': { '法杖': 0.3, '项链': 0.2, '魔法': 0.15 },
                    '弓箭手': { '弓': 0.25, '靴子': 0.15, '速度': 0.2 },
                    '盗贼': { '匕首': 0.3, '手套': 0.2, '暴击': 0.25 },
                    '牧师': { '治疗': 0.3, '防御': 0.15, '辅助': 0.2 }
                };
                
                const classBonus = bonuses[adventurerClass] || {};
                
                // 检查装备类型和属性匹配
                let bonus = 0;
                if (classBonus[item.slot]) bonus += classBonus[item.slot];
                if (item.attack > 0 && classBonus['攻击']) bonus += classBonus['攻击'];
                if (item.defense > 0 && classBonus['防御']) bonus += classBonus['防御'];
                if (item.speed > 0 && classBonus['速度']) bonus += classBonus['速度'];
                if (item.critRate > 0 && classBonus['暴击']) bonus += classBonus['暴击'];
                if (item.mp > 0 && classBonus['魔法']) bonus += classBonus['魔法'];
                
                return Math.min(bonus, 0.5); // 最大加50%加成
            }
            
            executeIdleBehavior(adventurer, behavior) {
                switch(behavior.action) {
                    case 'shopping':
                        adventurer.target = behavior.target;
                        adventurer.state = 'moving';
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 前往${behavior.target.type}购物`);
                        break;
                    case 'upgrade':
                        this.autoUpgradeEquipment(adventurer);
                        break;
                    case 'trade':
                        this.attemptTrade(adventurer);
                        break;
                    case 'wander':
                        this.startWandering(adventurer);
                        break;
                }
            }
            
            autoUpgradeEquipment(adventurer) {
                let upgraded = false;
                for (const item of adventurer.inventory) {
                    const currentEquip = adventurer.equipment[item.slot];
                    if (!currentEquip || this.calculateItemScore(item) > this.calculateItemScore(currentEquip) * 1.1) {
                        if (currentEquip) {
                            adventurer.inventory.push(currentEquip);
                        }
                        adventurer.equipment[item.slot] = item;
                        adventurer.inventory = adventurer.inventory.filter(i => i.id !== item.id);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 自动升级装备：${item.name}`);
                        this.updateEquipmentBonuses(adventurer);
                        upgraded = true;
                        break;
                    }
                }
                if (!upgraded) {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 没有可升级的装备`);
                }
            }
            
            attemptTrade(adventurer) {
                const tradePartner = this.adventurers.find(other => 
                    other.id !== adventurer.id && 
                    other.state !== 'dead' &&
                    this.canBenefitFromTrade(adventurer, other)
                );
                
                if (tradePartner) {
                    // 简化交易逻辑
                    const item1 = adventurer.inventory[0];
                    const item2 = tradePartner.inventory[0];
                    
                    if (item1 && item2 && this.wouldBenefitFromSwap(adventurer, tradePartner, item1, item2)) {
                        // 执行交易
                        adventurer.inventory = adventurer.inventory.filter(i => i.id !== item1.id);
                        tradePartner.inventory = tradePartner.inventory.filter(i => i.id !== item2.id);
                        adventurer.inventory.push(item2);
                        tradePartner.inventory.push(item1);
                        
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 与${tradePartner.name}交易了${item1.name}`);
                        tradePartner.log.push(`${new Date().toLocaleTimeString()} 与${adventurer.name}交易了${item2.name}`);
                    }
                } else {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 没有找到合适的交易对象`);
                }
            }
            
            startWandering(adventurer) {
                // 随机游荡 - 使用改进的分散式目标选择
                const scatteredPos = this.generateScatteredPosition(this.gameAreaWidth, this.gameAreaHeight, 50);
                const targetX = scatteredPos.x;
                const targetY = scatteredPos.y;
                
                adventurer.targetX = targetX;
                adventurer.targetY = targetY;
                adventurer.state = 'wandering';
                adventurer.log.push(`${new Date().toLocaleTimeString()} 开始游荡探索`);
            }
            updateAdventurerMoving(adventurer, deltaTime) {
                if (adventurer.target) {
                    const dx = adventurer.target.x - adventurer.x;
                    const dy = adventurer.target.y - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);

                    if (distance < 20) { // 增加接触距离到20，更容易开始战斗
                        if (adventurer.target.hasOwnProperty('hp')) {
                            adventurer.state = 'fighting';
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 开始与${adventurer.target.rank}${adventurer.target.type}战斗`);
                        } else if (adventurer.target.type === '旅馆') {
                            adventurer.state = 'resting';
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 在旅馆休息`);
                            // 处理建筑交互收入
                            const income = Math.floor(Config.BUILDING_FUNCTIONS['旅馆'].cost * 0.5); // 50%作为收入
                            this.processBuildingInteraction(adventurer.target, income);
                        } else if (adventurer.target.type === '饭店') {
                            adventurer.state = 'eating';
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 在饭店吃饭`);
                            // 处理建筑交互收入
                            const income = Math.floor(Config.BUILDING_FUNCTIONS['饭店'].cost * 0.5); // 50%作为收入
                            this.processBuildingInteraction(adventurer.target, income);
                        } else if (adventurer.target.type === '武器店' || adventurer.target.type === '防具店') {
                            if (adventurer.repairTarget) {
                                adventurer.state = 'repairing';
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 在${adventurer.target.type}修理装备`);
                            } else {
                                adventurer.state = 'shopping';
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 在${adventurer.target.type}购物`);
                            }
                            // 处理建筑交互收入
                            const income = Math.floor(Config.BUILDING_FUNCTIONS[adventurer.target.type].cost * 0.3); // 30%作为收入
                            this.processBuildingInteraction(adventurer.target, income);
                        } else if (adventurer.target.type === '魔法塔') {
                            if (adventurer.enchantTarget) {
                                adventurer.state = 'enchanting';
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 在魔法塔为${adventurer.enchantTarget.name}附魔`);
                            } else {
                                adventurer.state = 'idle';
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 在魔法塔没有找到需要附魔的装备`);
                            }
                            // 处理建筑交互收入
                            const income = Math.floor(Config.BUILDING_FUNCTIONS['魔法塔'].cost * 0.4); // 40%作为收入
                            this.processBuildingInteraction(adventurer.target, income);
                        } else if (adventurer.target.type === '铁匠铺') {
                            if (this.canUpgradeEquipment(adventurer)) {
                                adventurer.state = 'upgrading';
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 在铁匠铺升级装备`);
                            } else {
                                adventurer.state = 'idle';
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 在铁匠铺没有可升级的装备`);
                            }
                            // 处理建筑交互收入
                            const income = Math.floor(Config.BUILDING_FUNCTIONS['铁匠铺'].cost * 0.4); // 40%作为收入
                            this.processBuildingInteraction(adventurer.target, income);
                        } else if (adventurer.target.type === '炼金术师') {
                            adventurer.state = 'alchemy';
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 在炼金术师处制作药水`);
                            // 处理建筑交互收入
                            const income = Math.floor(Config.BUILDING_FUNCTIONS['炼金术师'].cost * 0.35); // 35%作为收入
                            this.processBuildingInteraction(adventurer.target, income);
                        }
                    } else {
                        // 提高移动速度，更快到达目标
                        const speed = Math.min(adventurer.speed * (deltaTime / 16) * 2.0, distance); // 增加100%移动速度，但不超过剩余距离
                        adventurer.x += (dx / distance) * speed;
                        adventurer.y += (dy / distance) * speed;
                        
                        // 防卡机制：如果移动距离过小，可能是卡住了
                        if (adventurer.lastPosition) {
                            const moveDistance = Math.sqrt(
                                Math.pow(adventurer.x - adventurer.lastPosition.x, 2) + 
                                Math.pow(adventurer.y - adventurer.lastPosition.y, 2)
                            );
                            
                            // 放宽卡住灵敏度：小于2像素算作可能卡住
                            if (moveDistance < 2.0) {
                                adventurer.stuckCounter = (adventurer.stuckCounter || 0) + 1;
                                
                                // 只有在连续较多帧都几乎未移动时，才判定为卡住（例如6帧）
                                if (adventurer.stuckCounter >= 6) {
                                    this.debugLog(`冒险者 ${adventurer.name} 可能卡住了，重置目标并设置短期移动冷却`);
                                    // 重置目标并设置短期冷却，防止立即被重新选为目标
                                    adventurer.target = null;
                                    adventurer.state = 'idle';
                                    adventurer.stuckCounter = 0;
                                    adventurer.moveCooldown = Date.now() + 1000; // 1 秒内不重新选择目标
                                    adventurer.log.push(`${new Date().toLocaleTimeString()} 移动卡住，重新规划路径`);
                                }
                            } else {
                                adventurer.stuckCounter = 0; // 重置卡住计数器
                            }
                        }
                        
                        // 记录当前位置
                        adventurer.lastPosition = { x: adventurer.x, y: adventurer.y };
                    }
                } else {
                    adventurer.state = 'idle';
                }
            }

            updateAdventurerFighting(adventurer, deltaTime) {
                // === 战斗安全检查 ===
                if (!adventurer.target || adventurer.target.hp <= 0) {
                    adventurer.target = null;
                    adventurer.state = 'idle';
                    return;
                }
                
                // === 检查战斗中的紧急退出条件 - 放宽条件以提高挂机体验 ===
                const shouldRetreatDueToHunger = adventurer.hunger <= Config.HUNGER_STARVING && adventurer.hp < adventurer.maxHp * 0.2;
                const shouldRetreatDueToInjury = adventurer.hp < adventurer.maxHp * 0.1; // 降低到10%才撤离
                
                if (shouldRetreatDueToHunger || shouldRetreatDueToInjury) {
                    adventurer.target = null;
                    adventurer.state = 'idle';
                    if (shouldRetreatDueToHunger) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 因极度饥饿被迫撤离战斗`);
                        // 设置冷却时间，防止立即重新战斗
                        adventurer.combatCooldown = Date.now() + 1000; // 减少到1秒冷却
                    } else {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 因生命垂危被迫撤离战斗`);
                        adventurer.combatCooldown = Date.now() + 2000; // 减少到2秒冷却
                    }
                    return;
                }

                // === 战斗逻辑 - 改进伤害计算并添加技能系统 ===
                if (adventurer.target && adventurer.target.hp > 0) {
                    // 检查是否可以使用技能
                    let damage = 0;
                    let isSkillUsed = false;
                    let skillResult = { used: false }; // 初始化skillResult变量
                    
                    // 尝试使用技能 - 进一步提高技能使用率以增强战斗体验
                    if (adventurer.mp >= 10 && Math.random() < 0.5) { // 50%几率使用技能，进一步降低MP消耗要求
                        // 检查技能冷却时间
                        const now = Date.now();
                        let canUseSkill = true;
                        const className = adventurer.class;
                        const skills = Config.CLASSES[className].skills;
                        
                        // 检查所有技能是否都在冷却中
                        for (const skill of skills) {
                            if (adventurer.skillCooldowns[skill] && adventurer.skillCooldowns[skill] > now) {
                                canUseSkill = false;
                                break;
                            }
                        }
                        
                        // 如果所有技能都在冷却中，则清除所有冷却时间（防止卡死）
                        if (!canUseSkill) {
                            const allOnCooldown = skills.every(skill => adventurer.skillCooldowns[skill] && adventurer.skillCooldowns[skill] > now);
                            if (allOnCooldown) {
                                adventurer.skillCooldowns = {};
                                canUseSkill = true;
                            }
                        }
                        
                        if (canUseSkill) {
                            skillResult = this.useAdventurerSkill(adventurer);
                            if (skillResult.used) {
                                damage = skillResult.damage;
                                isSkillUsed = true;
                                adventurer.log.push(`${new Date().toLocaleTimeString()} 使用技能${skillResult.skillName}！`);
                            }
                        }
                    }
                    
                    // 如果没有使用技能，则使用普通攻击
                    if (!isSkillUsed) {
                        // 计算暴击
                        const isCrit = Math.random() < adventurer.critRate;
                        
                        // 应用研究效果的攻击力加成
                        const researchAttackBonus = this.researchEffects.attackBonus || 0;
                        const finalAttack = adventurer.attack * (1 + researchAttackBonus);
                        
                        // 改进的伤害计算公式 - 提高基础伤害，减少防御减免
                        damage = Math.max(2, finalAttack - adventurer.target.defense * 0.3);
                        
                        // 根据等级差异调整伤害 - 放宽等级惩罚
                        const levelDiff = adventurer.level - adventurer.target.level;
                        if (levelDiff > 0) {
                            // 冒险者等级更高，伤害适度增加
                            damage *= (1 + Math.min(0.3, levelDiff * 0.03));
                        } else if (levelDiff < 0) {
                            // 冒险者等级更低，伤害减少但惩罚较轻
                            damage *= Math.max(0.7, 1 + levelDiff * 0.03);
                        }
                        
                        // 暴击伤害（仅适用于普通攻击）
                        if (isCrit) {
                            damage *= adventurer.critDamage;
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 对${adventurer.target.rank}${adventurer.target.type}造成了暴击！`);
                        }
                    }

                    // 应用伤害
                    if (isSkillUsed && skillResult.used && skillResult.isAoE) {
                        // 群体攻击伤害应用到多个目标
                        if (skillResult.targets) {
                            skillResult.targets.forEach(target => {
                                if (target && target.hp > 0) {
                                    // 对每个目标造成伤害（伤害递减）
                                    const targetDamage = Math.max(1, damage * (0.7 + Math.random() * 0.3));
                                    target.hp -= targetDamage;
                                    adventurer.log.push(`${new Date().toLocaleTimeString()} 群体技能命中${target.rank}${target.type}，造成${Math.floor(targetDamage)}点伤害！`);
                                }
                            });
                        }
                    } else {
                        // 单体伤害
                        adventurer.target.hp -= damage;
                        if (isSkillUsed && skillResult.used) {
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 使用技能${skillResult.skillName}命中${adventurer.target.rank}${adventurer.target.type}，造成${Math.floor(damage)}点伤害！`);
                        }
                    }

                    // 减少装备耐久度
                    this.reduceEquipmentDurability(adventurer, 0.01);

                    if (adventurer.target.hp <= 0) {
                        // 获得奖励 - 调整金币获取结构，打怪掉落少量金币
                        let goldGained = Math.floor(adventurer.target.rewardGold * 0.3); // 减少70%的金币奖励
                        let expGained = adventurer.target.rewardExp;

                        // 应用称号加成
                        if (this.titleEffects.goldBonus) {
                            goldGained = Math.floor(goldGained * (1 + this.titleEffects.goldBonus));
                        }
                        
                        // 应用研究效果加成
                        if (this.researchEffects.incomeBonus) {
                            goldGained = Math.floor(goldGained * (1 + this.researchEffects.incomeBonus));
                        }

                        adventurer.gold += goldGained;
                        adventurer.exp += expGained;

                        adventurer.log.push(`${new Date().toLocaleTimeString()} 击败${adventurer.target.rank}${adventurer.target.type}，获得${goldGained}金币和${expGained}经验`);

                        this.showResourceNotification(goldGained);

                        // 掉落装备（应用研究效果）
                        const baseDrop = adventurer.target.dropRate;
                        const titleDropBonus = this.titleEffects.dropRate || 0;
                        const researchDropBonus = this.researchEffects.dropRateBonus || 0;
                        const finalDropRate = baseDrop * (1 + titleDropBonus + researchDropBonus);
                        
                        if (Math.random() < finalDropRate) {
                            const equipment = this.createEquipment(
                                adventurer.target.equipmentDropLevel,
                                adventurer.target.equipmentDropRarity,
                                Config.EQUIPMENT_SLOTS[Math.floor(Math.random() * Config.EQUIPMENT_SLOTS.length)]
                            );
                            adventurer.inventory.push(equipment);
                            this.equipmentFound++;
                            // 更新任务进度 - 装备收集
                            this.updateQuestProgress('equipment_found');
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 获得${equipment.name}`);
                        }

                        const index = this.monsters.indexOf(adventurer.target);
                        if (index !== -1) {
                            this.monsters.splice(index, 1);
                        }

                        this.monstersDefeated++;
                        // 更新任务进度 - 击败怪物
                        this.updateQuestProgress('monsters_defeated');
                        
                        // 添加日志记录
                        this.addLogEntry(`${adventurer.name} 击败了 ${adventurer.target.rank}${adventurer.target.type} (Lv.${adventurer.target.level})`, 'success');

                        adventurer.target = null;
                        
                        // 战斗结束后检查状态，决定后续行为 - 进一步减少冷却时间以提高战斗频率
                        if (adventurer.hp < adventurer.maxHp * 0.1 || adventurer.hunger <= Config.HUNGER_STARVING) {
                            // 只有严重受伤或极度饥饿时才设置短暂冷却
                            adventurer.combatCooldown = Date.now() + 300; // 0.3秒冷却
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 战斗结束，快速休整恢复`);
                        } else {
                            // 状态良好时几乎无冷却
                            adventurer.combatCooldown = Date.now() + 100; // 0.1秒冷却
                        }
                        
                        // 如果启用了自动战斗且冒险者状态良好，立即寻找下一个目标
                        if (this.autoBattleEnabled && adventurer.hp >= adventurer.maxHp * 0.3 && adventurer.hunger > Config.HUNGER_CRITICAL * 0.5) {
                            // 几乎无延迟地立即寻找新目标
                            setTimeout(() => {
                                if (adventurer.state === 'idle') {
                                    adventurer.state = 'idle'; // 保持空闲状态以重新选择目标
                                }
                            }, 10); // 减少延迟到10毫秒
                        }
                        
                        adventurer.state = 'idle';

                        if (adventurer.exp >= adventurer.maxExp) {
                            this.levelUpAdventurer(adventurer);
                        }
                    }
                } else {
                    adventurer.target = null;
                    adventurer.state = 'idle';
                }
            }

            updateAdventurerResting(adventurer, deltaTime) {
                // 检查是否有特殊治疗类型
                const treatmentType = adventurer.treatmentType || 'normal';
                let healAmount = 10;
                let mpRestore = 20;
                // 旅馆动态定价：单冒险者总金钱的4%
                let cost = Math.max(1, Math.floor(adventurer.gold * 0.04));
                            
                if (treatmentType === 'inn') {
                    // 旅馆的加强治疗效果
                    healAmount = Math.floor(adventurer.maxHp * 0.3); // 恢复30%最大生命值
                    mpRestore = Math.floor(adventurer.maxMp * 0.5); // 恢复50%魔法值
                    // 旅馆动态定价：单冒险者总金钱的6%
                    cost = Math.max(1, Math.floor(adventurer.gold * 0.06));
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 接受旅馆专业治疗，恢复${healAmount}点生命值和${mpRestore}点魔法值（费用${cost}金）`);
                } else {
                    // 普通休息
                    healAmount = Math.floor(adventurer.maxHp * 0.1); // 恢复10%最大生命值
                    mpRestore = Math.floor(adventurer.maxMp * 0.2); // 恢复20%魔法值
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 休息恢复了${healAmount}点生命值和${mpRestore}点魔法值（费用${cost}金）`);
                }
                            
                if (adventurer.gold >= cost) {
                    adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + healAmount);
                    adventurer.mp = Math.min(adventurer.maxMp, adventurer.mp + mpRestore);
                    adventurer.gold -= cost;
                    this.gold += cost;
                    
                    // 处理建筑交互收入
                    if (adventurer.target) {
                        const income = Math.floor(cost * 0.5); // 50%作为建筑收入
                        this.processBuildingInteraction(adventurer.target, income);
                    }
                } else {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 金币不足，无法治疗（需要${cost}金，现有${adventurer.gold}金）`);
                }
                            
                // 清理治疗类型标记
                adventurer.treatmentType = null;
                adventurer.state = 'idle';
            }

            updateAdventurerEating(adventurer, deltaTime) {
                // 饭店动态定价：单冒险者总金钱的3%
                const baseCost = Math.max(1, Math.floor(adventurer.gold * 0.03));
                
                // 检查是否有特殊治疗类型
                const treatmentType = adventurer.treatmentType || 'normal';
                let healAmount = 20;
                let hungerRestore = 50;
                let actualCost = baseCost;
                            
                if (treatmentType === 'food') {
                    // 受伤状态下的营养恢复，费用更高
                    healAmount = Math.floor(adventurer.maxHp * 0.2); // 恢复20%最大生命值
                    hungerRestore = Math.floor(adventurer.maxHunger * 0.8); // 恢复80%饥饿值
                    actualCost = Math.max(1, Math.floor(baseCost * 1.5)); // 特殊治疗费用增加50%
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 受伤状态下的营养餐，恢复${healAmount}点生命值和${hungerRestore}点饥饿值（费用${actualCost}金）`);
                } else {
                    // 普通进食
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 吃饭恢复了${healAmount}点生命值和${hungerRestore}点饥饿值（费用${actualCost}金）`);
                }
                
                // 检查金币是否足够
                if (adventurer.gold >= actualCost) {
                    adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + healAmount);
                    adventurer.hunger = Math.min(adventurer.maxHunger, adventurer.hunger + hungerRestore);
                    adventurer.gold -= actualCost;
                    this.gold += actualCost;
                    
                    // 处理建筑交互收入
                    if (adventurer.target) {
                        const income = Math.floor(actualCost * 0.5); // 50%作为建筑收入
                        this.processBuildingInteraction(adventurer.target, income);
                    }
                } else {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 金币不足，无法付款（需要${actualCost}金，现有${adventurer.gold}金）`);
                }
                            
                // 清理治疗类型标记
                adventurer.treatmentType = null;
                adventurer.state = 'idle';
            }

            updateAdventurerShopping(adventurer, deltaTime) {
                // 模拟购物行为
                if (adventurer.gold >= 20 && Math.random() < 0.5) {
                    const equipment = this.createEquipment(adventurer.level, Math.floor(Math.random() * 3),
                        Config.EQUIPMENT_SLOTS[Math.floor(Math.random() * Config.EQUIPMENT_SLOTS.length)]);
                    adventurer.inventory.push(equipment);
                    adventurer.gold -= 20;
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 购买了${equipment.name}`);
                    
                    // 处理建筑交互收入
                    if (adventurer.target) {
                        const income = Math.floor(20 * 0.3); // 30%作为建筑收入
                        this.processBuildingInteraction(adventurer.target, income);
                    }
                } else {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 浏览了商店，但没有购买任何东西`);
                    
                    // 处理建筑交互收入（即使没有购买也产生少量收入）
                    if (adventurer.target) {
                        const income = Math.floor(1 * 0.3); // 30%作为建筑收入
                        this.processBuildingInteraction(adventurer.target, income);
                    }
                }
                adventurer.state = 'idle';
            }

            updateAdventurerRepairing(adventurer, deltaTime) {
                if (adventurer.repairTarget) {
                    const equipment = adventurer.repairTarget;
                    
                    // 确保装备对象存在且有耐久度属性
                    if (!equipment || typeof equipment.durability === 'undefined' || typeof equipment.maxDurability === 'undefined') {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 装备数据异常，无法修理`);
                        adventurer.repairTarget = null;
                        adventurer.state = 'idle';
                        return;
                    }
                    
                    // 动态定价：修理费用基于装备价值和冒险者总金钱
                    const baseRepairCost = Math.floor(equipment.value * 0.2 * (1 - equipment.durability / equipment.maxDurability));
                    const repairCost = Math.max(1, Math.floor(baseRepairCost * (1 + adventurer.gold * 0.0001)));
                    
                    // 金币安全检查
                    adventurer.gold = Math.max(0, adventurer.gold);
                    
                    if (adventurer.gold >= repairCost && repairCost > 0) {
                        // 修理装备
                        equipment.durability = equipment.maxDurability;
                        adventurer.gold = Math.max(0, adventurer.gold - repairCost);
                        this.gold = Math.max(0, this.gold + repairCost);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 修理了${equipment.name}，花费${repairCost}金币`);
                        
                        // 处理建筑交互收入
                        if (adventurer.target) {
                            const income = Math.floor(repairCost * 0.3); // 30%作为建筑收入
                            this.processBuildingInteraction(adventurer.target, income);
                        }
                    } else if (repairCost <= 0) {
                        // 装备已经完全修复
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}无需修理`);
                    } else {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 金币不足，无法修理${equipment.name}（需要${repairCost}金币）`);
                    }
                    
                    adventurer.repairTarget = null;
                }
                adventurer.state = 'idle';
            }
            
            /**
             * 更新冒险者紧急休息状态（重伤时使用）
             * 每秒恢复少量生命值，然后转入空闲状态
             * @param {Object} adventurer - 冒险者对象 
             * @param {number} deltaTime - 时间增量
             */
            updateAdventurerEmergencyRest(adventurer, deltaTime) {
                const restDuration = 5000; // 5秒紧急休息
                const restElapsed = Date.now() - adventurer.restStartTime;
                
                // 每秒恢复3%的最大生命值（提高恢复速度）
                const healRate = adventurer.maxHp * 0.03 * (deltaTime / 1000);
                adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + healRate);
                
                // 检查是否休息完成或生命值恢复到安全水平
                if (restElapsed >= restDuration || adventurer.hp >= adventurer.maxHp * 0.3) {
                    adventurer.state = 'idle';
                    adventurer.restStartTime = null;
                    const recoveredHp = Math.floor(adventurer.maxHp * 0.15); // 总共恢复15%生命值
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 紧急休息结束，恢复了${recoveredHp}点生命值`);
                }
            }
            
            /**
             * 更新冒险者就地休息状态（轻伤时使用）
             * 缓慢恢复生命值，比紧急休息慢但持续时间更长
             * @param {Object} adventurer - 冒险者对象
             * @param {number} deltaTime - 时间增量
             */
            updateAdventurerFieldRest(adventurer, deltaTime) {
                const restDuration = 8000; // 8秒就地休息
                const restElapsed = Date.now() - adventurer.restStartTime;
                
                // 每秒恢复2.5%的最大生命值（提高恢复速度）
                const healRate = adventurer.maxHp * 0.025 * (deltaTime / 1000);
                adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + healRate);
                
                // 每秒恢复少量饥饿值
                const hungerRate = adventurer.maxHunger * 0.015 * (deltaTime / 1000);
                adventurer.hunger = Math.min(adventurer.maxHunger, adventurer.hunger + hungerRate);
                
                // 检查是否休息完成或生命值恢复到安全水平
                if (restElapsed >= restDuration || adventurer.hp >= adventurer.maxHp * 0.5) {
                    adventurer.state = 'idle';
                    adventurer.restStartTime = null;
                    const recoveredHp = Math.floor(adventurer.maxHp * 0.2); // 总共恢复20%生命值
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 就地休息结束，恢复了${recoveredHp}点生命值`);
                }
            }

            /**
             * 更新冒险者装备升级状态
             * 在铁匠铺进行装备升级，提升装备属性
             * @param {Object} adventurer - 冒险者对象
             * @param {number} deltaTime - 时间增量
             */
            updateAdventurerUpgrading(adventurer, deltaTime) {
                // 检查是否有可升级的装备
                let upgraded = false;
                for (const item of adventurer.inventory) {
                    const currentEquip = adventurer.equipment[item.slot];
                    if (!currentEquip || this.calculateItemScore(item) > this.calculateItemScore(currentEquip) * 1.1) {
                        // 动态定价：升级费用基于装备价值和冒险者总金钱
                        const baseUpgradeCost = Math.floor(item.value * 0.5);
                        const upgradeCost = Math.max(1, Math.floor(baseUpgradeCost * (1 + adventurer.gold * 0.00008)));
                        
                        // 检查金币是否充足
                        if (adventurer.gold >= upgradeCost) {
                            // 执行装备升级
                            if (currentEquip) {
                                adventurer.inventory.push(currentEquip);
                            }
                            adventurer.equipment[item.slot] = item;
                            adventurer.inventory = adventurer.inventory.filter(i => i.id !== item.id);
                            
                            // 扣除费用
                            adventurer.gold = Math.max(0, adventurer.gold - upgradeCost);
                            this.gold = Math.max(0, this.gold + upgradeCost);
                            
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 在铁匠铺升级了${item.name}，花费${upgradeCost}金币`);
                            
                            // 处理建筑交互收入
                            if (adventurer.target) {
                                const income = Math.floor(upgradeCost * 0.4); // 40%作为建筑收入
                                this.processBuildingInteraction(adventurer.target, income);
                            }
                            this.updateEquipmentBonuses(adventurer);
                            upgraded = true;
                            break;
                        } else {
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 金币不足，无法升级${item.name}（需要${upgradeCost}金币）`);
                        }
                    }
                }
                
                if (!upgraded) {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 在铁匠铺没有找到可升级的装备`);
                }
                
                adventurer.state = 'idle';
            }

            /**
             * 更新冒险者附魔状态
             * 在魔法塔进行装备附魔，提升装备属性
             * @param {Object} adventurer - 冒险者对象
             * @param {number} deltaTime - 时间增量
             */
            updateAdventurerEnchanting(adventurer, deltaTime) {
                if (adventurer.enchantTarget) {
                    const equipment = adventurer.enchantTarget;
                    
                    // 确保装备对象存在
                    if (!equipment) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 装备数据异常，无法附魔`);
                        adventurer.enchantTarget = null;
                        adventurer.state = 'idle';
                        return;
                    }
                    
                    // 动态定价：附魔费用基于装备价值和冒险者总金钱
                    const baseEnchantCost = Math.floor(equipment.value * 0.3);
                    const enchantCost = Math.max(1, Math.floor(baseEnchantCost * (1 + adventurer.gold * 0.00005)));
                    
                    // 金币安全检查
                    adventurer.gold = Math.max(0, adventurer.gold);
                    
                    if (adventurer.gold >= enchantCost && enchantCost > 0) {
                        // 附魔装备 - 提升装备属性
                        const enchantBonus = 0.1 + (Math.random() * 0.1); // 10%-20%属性提升
                        equipment.attack = Math.floor(equipment.attack * (1 + enchantBonus));
                        equipment.defense = Math.floor(equipment.defense * (1 + enchantBonus));
                        equipment.hp = Math.floor(equipment.hp * (1 + enchantBonus));
                        equipment.mp = Math.floor(equipment.mp * (1 + enchantBonus));
                        
                        // 更新装备价值
                        equipment.value = Math.floor(equipment.value * 1.5);
                        
                        // 标记装备已附魔
                        equipment.isEnchanted = true;
                        
                        // 扣除费用
                        adventurer.gold = Math.max(0, adventurer.gold - enchantCost);
                        this.gold = Math.max(0, this.gold + enchantCost);
                        
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 在魔法塔附魔了${equipment.name}，花费${enchantCost}金币，属性提升${Math.floor(enchantBonus * 100)}%`);
                        
                        // 处理建筑交互收入
                        if (adventurer.target) {
                            const income = Math.floor(enchantCost * 0.4); // 40%作为建筑收入
                            this.processBuildingInteraction(adventurer.target, income);
                        }
                    } else if (enchantCost <= 0) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}无法附魔`);
                    } else {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 金币不足，无法附魔${equipment.name}（需要${enchantCost}金币）`);
                    }
                    
                    adventurer.enchantTarget = null;
                }
                adventurer.state = 'idle';
            }
            
            /**
             * 更新冒险者游荡状态
             * 处理冒险者的随机移动和探索行为
             * @param {Object} adventurer - 冒险者对象
             * @param {number} deltaTime - 时间增量
             */
            updateAdventurerWandering(adventurer, deltaTime) {
                // 检查是否到达目标位置
                if (adventurer.targetX !== null && adventurer.targetY !== null) {
                    const dx = adventurer.targetX - adventurer.x;
                    const dy = adventurer.targetY - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance < 15) {
                        // 到达目标位置，切换回空闲状态
                        adventurer.targetX = null;
                        adventurer.targetY = null;
                        adventurer.state = 'idle';
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 完成游荡，开始寻找新的目标`);
                        return;
                    }
                    
                    // 向目标位置移动
                    const speed = adventurer.speed * (deltaTime / 16) * 1.2; // 游荡时移动速度适中
                    adventurer.x += (dx / distance) * speed;
                    adventurer.y += (dy / distance) * speed;
                    
                    // 在移动过程中检查是否发现了怪物 - 提高发现概率
                    if (Math.random() < 0.05) { // 5%的概率在游荡中发现怪物
                        const nearbyMonster = this.findNearbyMonster(adventurer, 150); // 增加搜索半径
                        if (nearbyMonster) {
                            adventurer.target = nearbyMonster;
                            adventurer.state = 'moving';
                            adventurer.targetX = null;
                            adventurer.targetY = null;
                            adventurer.log.push(`${new Date().toLocaleTimeString()} 游荡中发现了${nearbyMonster.rank}${nearbyMonster.type}！`);
                            return;
                        }
                    }
                } else {
                    // 没有目标，切换回空闲状态重新选择行为
                    adventurer.state = 'idle';
                }
            }
            
            /**
             * 更新冒险者炼金术状态
             * 在炼金术师处制作药水，恢复生命值或魔法值
             * @param {Object} adventurer - 冒险者对象
             * @param {number} deltaTime - 时间增量
             */
            updateAdventurerAlchemy(adventurer, deltaTime) {
                // 动态定价：制作药水的费用基于冒险者总金钱
                // 基础费用为20金币，根据冒险者财富调整
                const baseCost = 20;
                const wealthMultiplier = Math.min(0.5, adventurer.gold * 0.0002); // 财富乘数，最高50%
                const potionCost = Math.max(1, Math.floor(baseCost * (1 + wealthMultiplier)));
                
                // 金币安全检查
                adventurer.gold = Math.max(0, adventurer.gold);
                
                if (adventurer.gold >= potionCost && potionCost > 0) {
                    // 制作药水
                    adventurer.gold = Math.max(0, adventurer.gold - potionCost);
                    this.gold = Math.max(0, this.gold + potionCost);
                    
                    // 随机生成不同类型的药水
                    const potionTypes = [
                        { name: "治疗药水", effect: "heal", value: 0.3 }, // 恢复30%生命值
                        { name: "强力治疗药水", effect: "heal", value: 0.5 }, // 恢复50%生命值
                        { name: "魔法药水", effect: "mana", value: 0.3 }, // 恢复30%魔法值
                        { name: "强力魔法药水", effect: "mana", value: 0.5 }  // 恢复50%魔法值
                    ];
                    
                    const potion = potionTypes[Math.floor(Math.random() * potionTypes.length)];
                    
                    if (potion.effect === "heal") {
                        const healAmount = Math.floor(adventurer.maxHp * potion.value);
                        adventurer.hp = Math.min(adventurer.maxHp, adventurer.hp + healAmount);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 在炼金术师处制作了${potion.name}，花费${potionCost}金币，恢复了${healAmount}点生命值`);
                        
                        // 处理建筑交互收入
                        if (adventurer.target) {
                            const income = Math.floor(potionCost * 0.35); // 35%作为建筑收入
                            this.processBuildingInteraction(adventurer.target, income);
                        }
                    } else if (potion.effect === "mana") {
                        const manaAmount = Math.floor(adventurer.maxMana * potion.value);
                        adventurer.mana = Math.min(adventurer.maxMana, adventurer.mana + manaAmount);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 在炼金术师处制作了${potion.name}，花费${potionCost}金币，恢复了${manaAmount}点魔法值`);
                        
                        // 处理建筑交互收入
                        if (adventurer.target) {
                            const income = Math.floor(potionCost * 0.35); // 35%作为建筑收入
                            this.processBuildingInteraction(adventurer.target, income);
                        }
                    }
                } else if (potionCost <= 0) {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 炼金术师处无法制作药水`);
                } else {
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 金币不足，无法制作药水（需要${potionCost}金币）`);
                }
                
                adventurer.state = 'idle';
            }
            
            /**
             * 寻找附近的怪物
             * @param {Object} adventurer - 冒险者对象
             * @param {number} radius - 搜索半径
             * @returns {Object|null} 找到的怪物或null
             */
            findNearbyMonster(adventurer, radius) {
                return this.monsters.find(monster => {
                    const dx = monster.x - adventurer.x;
                    const dy = monster.y - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    return distance <= radius;
                });
            }
            
            /**
             * 寻找附近的多个怪物（用于群体攻击）
             * @param {Object} adventurer - 冒险者对象
             * @param {number} radius - 搜索半径
             * @param {number} maxCount - 最大数量
             * @returns {Array} 找到的怪物数组
             */
            findNearbyMonsters(adventurer, radius, maxCount = 3) {
                const nearbyMonsters = this.monsters.filter(monster => {
                    const dx = monster.x - adventurer.x;
                    const dy = monster.y - adventurer.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    return distance <= radius;
                });
                
                // 按距离排序，返回最近的几个
                nearbyMonsters.sort((a, b) => {
                    const distA = Math.sqrt(Math.pow(a.x - adventurer.x, 2) + Math.pow(a.y - adventurer.y, 2));
                    const distB = Math.sqrt(Math.pow(b.x - adventurer.x, 2) + Math.pow(b.y - adventurer.y, 2));
                    return distA - distB;
                });
                
                return nearbyMonsters.slice(0, maxCount);
            }

            /**
             * 生成分散式位置，避免实体聚集到地图中心
             * @param {number} maxWidth - 最大宽度
             * @param {number} maxHeight - 最大高度
             * @param {number} margin - 边距
             * @returns {Object} 包含 x, y 坐标的对象
             */
            /**
             * 生成分散式位置 - 位置分布系统
             * 创建一个避免中心聚集的随机位置，使游戏元素分布更加自然
             * 采用边缘优先策略，提高游戏元素的可见性和可交互性
             * 支持自定义边距和区域范围，适应不同场景需求
             * 
             * 分布策略：
             * 1. 基础随机分布 - 在指定区域内生成随机坐标
             * 2. 中心回避机制 - 避免元素过于集中在地图中心
             * 3. 边缘优先策略 - 增加边缘区域的生成概率
             * 4. 距离权重计算 - 根据距离中心远近调整分布
             * 
             * 边缘优先特点：
             * - 30%中心距离阈值触发边缘选择
             * - 40%概率重新选择边缘位置
             * - 四个边缘区域均匀分布
             * - 保持整体随机性避免规律
             * 
             * 坐标生成机制：
             * - X坐标 = 边距 + 随机值 × (最大宽度 - 2×边距)
             * - Y坐标 = 边距 + 随机值 × (最大高度 - 2×边距)
             * - 确保元素不会贴边或越界
             * - 边距参数提供安全缓冲区域
             * 
             * 距离计算原理：
             * - 中心点坐标 = (最大宽度/2, 最大高度/2)
             * - 欧几里得距离公式计算实际距离
             * - 最大距离 = √(中心X² + 中心Y²)
             * - 距离比值用于概率判断
             * 
             * 边缘区域分配：
             * - 上边缘：Y坐标靠近上边界
             * - 右边缘：X坐标靠近右边界
             * - 下边缘：Y坐标靠近下边界
             * - 左边缘：X坐标靠近左边界
             * 
             * @param {number} maxWidth - 最大宽度范围
             * @param {number} maxHeight - 最大高度范围
             * @param {number} margin - 边界边距，默认50像素
             * @returns {Object} 包含x,y坐标的对象
             */
            generateScatteredPosition(maxWidth, maxHeight, margin = 50) {
                // 使用全地图范围，避免中心偏向
                const x = margin + Math.random() * (maxWidth - 2 * margin);
                const y = margin + Math.random() * (maxHeight - 2 * margin);
                
                // 添加分散因子，优先选择边缘区域
                const centerX = maxWidth / 2;
                const centerY = maxHeight / 2;
                const distanceFromCenter = Math.sqrt((x - centerX) ** 2 + (y - centerY) ** 2);
                const maxDistance = Math.sqrt(centerX ** 2 + centerY ** 2);
                
                // 如果太接近中心，有一定几率重新选择边缘位置
                if (distanceFromCenter < maxDistance * 0.3 && Math.random() < 0.4) {
                    // 优先选择边缘位置
                    const side = Math.floor(Math.random() * 4);
                    switch(side) {
                        case 0: // 上边
                            return { x: margin + Math.random() * (maxWidth - 2 * margin), y: margin + Math.random() * 100 };
                        case 1: // 右边
                            return { x: maxWidth - margin - Math.random() * 100, y: margin + Math.random() * (maxHeight - 2 * margin) };
                        case 2: // 下边
                            return { x: margin + Math.random() * (maxWidth - 2 * margin), y: maxHeight - margin - Math.random() * 100 };
                        case 3: // 左边
                            return { x: margin + Math.random() * 100, y: margin + Math.random() * (maxHeight - 2 * margin) };
                    }
                }
                
                return { x, y };
            }
            
            /**
             * 生成半集中式位置，让怪物更容易被发现和战斗
             * @param {number} maxWidth - 最大宽度
             * @param {number} maxHeight - 最大高度
             * @param {number} margin - 边距
             * @returns {Object} 包含 x, y 坐标的对象
             */
            generateSemiConcentratedPosition(maxWidth, maxHeight, margin = 100) {
                // 70%几率在中心区域生成，30%在边缘区域
                if (Math.random() < 0.7) {
                    // 在中心60%区域生成
                    const centerWidth = maxWidth * 0.6;
                    const centerHeight = maxHeight * 0.6;
                    const startX = (maxWidth - centerWidth) / 2;
                    const startY = (maxHeight - centerHeight) / 2;
                    
                    return {
                        x: startX + margin + Math.random() * (centerWidth - 2 * margin),
                        y: startY + margin + Math.random() * (centerHeight - 2 * margin)
                    };
                } else {
                    // 在边缘区域生成
                    return this.generateScatteredPosition(maxWidth, maxHeight, margin);
                }
            }
            
            /**
             * 更新怪物状态 - 怪物AI系统的核心更新方法
             * 负责处理怪物的AI决策、移动、技能冷却和边界检测等所有行为
             * 这是怪物AI系统的主更新循环，每帧调用一次
             * 
             * 更新流程：
             * 1. 更新怪物AI状态（决策系统）
             * 2. 根据行为模式移动（运动系统）
             * 3. 更新技能冷却时间（战斗系统）
             * 4. 边界检测（位置约束）
             * 
             * @param {Object} monster - 怪物对象，包含所有属性和状态信息
             * @param {number} deltaTime - 时间差值（毫秒），用于计算各种时间相关的变化
             * @param {number} index - 怪物在怪物数组中的索引位置
             */
            /**
             * 更新怪物状态 - 怪物管理系统
             * 综合更新怪物的AI、移动、技能和边界检测
             * 每帧调用确保怪物行为连贯性
             * 支持完整的怪物生命周期管理
             * 
             * 更新流程：
             * 1. 更新怪物AI状态 - 决策逻辑处理
             * 2. 更新怪物移动 - 位置变化计算
             * 3. 更新技能冷却 - 使用间隔管理
             * 4. 检查边界碰撞 - 区域限制处理
             * 
             * AI系统集成：
             * - 调用updateMonsterAI处理决策
             * - 支持复杂状态机行为
             * - 目标选择和状态切换
             * - 行为模式动态调整
             * 
             * 移动系统集成：
             * - 调用updateMonsterMovement处理位置
             * - 支持多种移动模式
             * - 速度和方向计算
             * - 碰撞检测处理
             * 
             * 技能管理：
             * - 技能冷却时间递减
             * - 防止技能连续使用
             * - 保持游戏平衡性
             * - 支持技能间隔控制
             * 
             * 边界处理：
             * - 调用checkMonsterBounds处理边界
             * - 防止怪物移出游戏区域
             * - 碰撞反弹机制
             * - 位置修正处理
             * 
             * @param {Object} monster - 怪物对象
             * @param {number} deltaTime - 距离上次更新的时间差(毫秒)
             * @param {number} index - 怪物在数组中的索引
             */
            updateMonster(monster, deltaTime, index) {
                // 更新怪物AI状态 - 处理怪物的决策逻辑
                // 包括目标选择、状态切换等AI行为
                this.updateMonsterAI(monster, deltaTime);
                
                // 根据行为模式移动 - 处理怪物的运动逻辑
                // 根据当前状态和行为模式计算新的位置
                this.updateMonsterMovement(monster, deltaTime);
                
                // 技能冷却更新 - 管理怪物技能的使用间隔
                // 确保怪物不会连续使用技能，保持游戏平衡
                if (monster.lastSkillUse > 0) {
                    monster.lastSkillUse -= deltaTime; // 减少技能冷却时间
                }
                
                // 边界检测 - 确保怪物不会移出游戏区域
                // 处理怪物与地图边界的碰撞和反弹
                this.checkMonsterBounds(monster);
            }
            
            /**
             * 清理长时间未被击败的怪物 - 内存管理
             * 定期清理5分钟内未被击败的怪物，防止内存泄漏
             * 保持游戏性能稳定，避免对象积累过多
             * 
             * 清理策略：
             * 1. 检查怪物生成时间
             * 2. 超过5分钟未被击败的怪物将被移除
             * 3. 添加日志记录清理操作
             * 4. 更新UI显示
             */
            cleanupOldMonsters() {
                const now = Date.now();
                const cleanupThreshold = this.monsterCleanupTime; // 5分钟
                let cleanedCount = 0;
                
                // 从后向前遍历，避免索引问题
                for (let i = this.monsters.length - 1; i >= 0; i--) {
                    const monster = this.monsters[i];
                    // 检查怪物是否超过清理阈值
                    if (monster.spawnTime && (now - monster.spawnTime) > cleanupThreshold) {
                        // 移除怪物
                        this.monsters.splice(i, 1);
                        cleanedCount++;
                    }
                }
                
                // 如果有清理操作，记录日志
                if (cleanedCount > 0) {
                    this.addLogEntry(`清理了${cleanedCount}只长时间未被击败的怪物`, 'info');
                    this.debugLog(`清理了${cleanedCount}只长时间未被击败的怪物`);
                }
            }
            
            /**
             * 更新怪物AI状态 - 怪物决策系统的核心方法
             * 负责处理怪物的目标选择、状态切换和行为决策
             * 采用基于距离的威胁评估系统和多样化的行为模式
             * 实现智能的怪物行为决策机制
             * 
             * AI决策流程：
             * 1. 检测附近的冒险者（威胁评估）
             * 2. 如果有威胁：
             *    a. 选择最近的目标
             *    b. 根据距离切换状态（攻击/追击）
             * 3. 如果无威胁：
             *    a. 重置状态
             *    b. 执行预设行为模式
             * 
             * 威胁评估系统：
             * - 过滤已死亡冒险者避免无效目标
             * - 计算欧几里得距离判断威胁范围
             * - 警戒半径决定怪物感知能力
             * - 支持多目标威胁评估
             * 
             * 目标选择机制：
             * - 最近距离优先选择策略
             * - 遍历所有威胁目标
             * - 实时计算动态距离
             * - 确保目标选择准确性
             * 
             * 状态切换逻辑：
             * - 攻击状态：距离<30像素
             * - 追击状态：距离≥30像素
             * - 巡逻状态：无威胁时重置
             * - 状态转换平滑自然
             * 
             * 行为模式集成：
             * - 无威胁时执行预设行为
             * - 调用executeMonsterBehavior处理
             * - 支持多样化行为模式
             * - 保持怪物个性特征
             * 
             * @param {Object} monster - 怪物对象，包含所有属性和状态信息
             * @param {number} deltaTime - 时间差值（毫秒），用于时间相关计算
             */
            updateMonsterAI(monster, deltaTime) {
                // 检测附近的冒险者 - 威胁评估系统（优化版）
                // 过滤出在怪物警戒范围内的活跃冒险者，增加一些智能判断
                // 优化：只检查前10个冒险者以提高性能
                const maxCheckCount = Math.min(10, this.adventurers.length);
                const nearbyAdventurers = [];
                for (let i = 0; i < maxCheckCount; i++) {
                    const adv = this.adventurers[i];
                    // 排除已死亡的冒险者
                    if (adv.state === 'dead') continue;
                    // 排除正在紧急休息或就地休息的冒险者（他们可能不会构成威胁）
                    if (adv.state === 'emergency_rest' || adv.state === 'field_rest') continue;
                    // 排除正在吃饭的冒险者（他们可能不会立即构成威胁）
                    if (adv.state === 'eating') continue;
                    // 计算与冒险者的距离
                    const dx = adv.x - monster.x;
                    const dy = adv.y - monster.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    // 判断是否在警戒范围内
                    if (distance <= monster.aggroRadius) {
                        nearbyAdventurers.push(adv);
                    }
                }
                
                // 如果检测到附近有冒险者（存在威胁）
                if (nearbyAdventurers.length > 0) {
                    // 选择最优目标 - 综合考虑距离、威胁等级和状态
                    let bestAdventurer = null;
                    let bestScore = -Infinity;
                    
                    // 遍历所有附近的冒险者，计算每个冒险者的威胁评分
                    // 优化：限制最多检查5个冒险者以提高性能
                    const maxCheckCount = Math.min(5, nearbyAdventurers.length);
                    for (let i = 0; i < maxCheckCount; i++) {
                        const adv = nearbyAdventurers[i];
                        const dx = adv.x - monster.x;
                        const dy = adv.y - monster.y;
                        const distance = Math.sqrt(dx * dx + dy * dy);
                        
                        // 计算威胁评分（距离越近、等级越高、生命值越满，威胁越大）
                        // 距离权重（距离越近威胁越大）
                        const distanceScore = Math.max(0, 1 - (distance / monster.aggroRadius));
                        // 等级权重（等级越高威胁越大）
                        const levelScore = adv.level / 50; // 假设最高等级为50
                        // 生命值权重（生命值越高威胁越大）
                        const hpScore = adv.hp / adv.maxHp;
                        // 状态权重（战斗中的冒险者威胁更大）
                        let stateScore = 1.0;
                        if (adv.state === 'fighting' || adv.state === 'moving') {
                            stateScore = 1.5; // 战斗或移动中的冒险者威胁更大
                        } else if (adv.state === 'wandering') {
                            stateScore = 1.2; // 游荡中的冒险者有一定威胁
                        } else if (adv.state === 'idle') {
                            stateScore = 0.8; // 空闲的冒险者威胁较小
                        }
                        // 装备权重（装备更好的冒险者威胁更大）
                        // 优化：简化装备评分计算
                        let equipmentCount = 0;
                        for (const slot in adv.equipment) {
                            if (adv.equipment[slot]) equipmentCount++;
                        }
                        const equipmentScore = equipmentCount / 8; // 假设最多8件装备
                        
                        // 综合评分
                        const threatScore = (distanceScore * 0.3 + levelScore * 0.25 + hpScore * 0.2 + stateScore * 0.15 + equipmentScore * 0.1) * 100;
                        
                        if (threatScore > bestScore) {
                            bestScore = threatScore;
                            bestAdventurer = adv;
                        }
                    }
                    
                    // 根据最优目标切换状态
                    if (bestAdventurer) {
                        const dx = bestAdventurer.x - monster.x;
                        const dy = bestAdventurer.y - monster.y;
                        const distance = Math.sqrt(dx * dx + dy * dy);
                        
                        // 如果当前已有目标且目标未改变，保持当前状态以避免频繁切换
                        const shouldSwitchTarget = !monster.target || monster.target.id !== bestAdventurer.id;
                        
                        // 距离很近，进入攻击状态
                        if (distance < 35) { // 稍微增加攻击距离
                            // 只有当目标改变或当前不在攻击状态时才切换
                            if (shouldSwitchTarget || monster.state !== 'attack') {
                                monster.state = 'attack';
                                monster.target = bestAdventurer; // 设置攻击目标
                            }
                        } else {
                            // 距离较远，进入追击状态
                            // 只有当目标改变或当前不在追击状态时才切换
                            if (shouldSwitchTarget || monster.state !== 'chase') {
                                monster.state = 'chase';
                                // 设置追击目标位置
                                monster.targetX = bestAdventurer.x;
                                monster.targetY = bestAdventurer.y;
                            }
                        }
                    }
                } else {
                    // 如果没有检测到附近冒险者（无威胁）
                    // 检查是否需要重置状态
                    if (monster.state === 'chase' || monster.state === 'attack') {
                        monster.state = 'patrol'; // 重置为巡逻状态
                        monster.target = null; // 清除目标
                        monster.targetX = null; // 清除目标位置
                        monster.targetY = null; // 清除目标位置
                    }
                    // 如果怪物处于攻击状态但目标已死亡或不存在，重置状态
                    else if (monster.state === 'attack' && (!monster.target || monster.target.state === 'dead')) {
                        monster.state = 'patrol';
                        monster.target = null;
                    }
                    
                    // 按照行为模式执行 - 执行预设的行为模式
                    // 添加一个冷却时间，避免过于频繁的行为切换
                    if (!monster.lastBehaviorUpdate || Date.now() - monster.lastBehaviorUpdate > 1000) {
                        this.executeMonsterBehavior(monster, deltaTime);
                        monster.lastBehaviorUpdate = Date.now();
                    }
                }
            }
            
            /**
             * 执行怪物行为模式 - 怪物个性化行为系统
             * 根据怪物的预设行为模式执行相应的动作
             * 不同的行为模式使怪物具有多样化的表现和策略
             * 支持5种不同的行为模式实现丰富AI表现
             * 
             * 行为模式类型：
             * 1. 游荡 - 随机移动，无固定目标
             * 2. 巡逻 - 在区域内有目标地移动
             * 3. 守护 - 在固定点附近活动
             * 4. 狂暴 - 移动速度提升
             * 5. 群体 - 与其他怪物协同行动
             * 
             * 游荡行为特点：
             * - 每3-5秒随机改变移动方向
             * - 模拟无目的的自然游走
             * - 时间间隔增加随机性
             * - 方向改变记录避免频繁转向
             * 
             * 巡逻行为特点：
             * - 有目标地点的移动模式
             * - 接近目标点时生成新目标
             * - 使用分散式位置生成避免聚集
             * - 保持区域内有序移动
             * 
             * 守护行为特点：
             * - 围绕固定点小范围活动
             * - 距离守护点过远时返回
             * - 初始化守护点为生成位置
             * - 保持区域控制特性
             * 
             * 狂暴行为特点：
             * - 永久性速度提升20%
             * - 增强怪物威胁性
             * - 适用于特殊怪物类型
             * - 速度加成不可逆
             * 
             * 群体行为特点：
             * - 与其他同类怪物协同
             * - 100像素范围内寻找同伴
             * - 跟随最近的群体领袖
             * - 形成集群效应增强威胁
             * 
             * @param {Object} monster - 怪物对象，包含行为模式信息
             * @param {number} deltaTime - 时间差值（毫秒），用于时间相关计算
             */
            executeMonsterBehavior(monster, deltaTime) {
                // 根据怪物的行为模式执行相应动作
                switch(monster.behavior) {
                    case '游荡':
                        // 游荡行为 - 随机移动，模拟无目的的游走
                        // 每隔2-4秒随机改变移动方向（提高频率使移动更活跃）
                        if (!monster.lastDirectionChange || Date.now() - monster.lastDirectionChange > 2000 + Math.random() * 2000) {
                            monster.direction = Math.random() * Math.PI * 2; // 随机方向（弧度）
                            monster.lastDirectionChange = Date.now(); // 记录方向改变时间
                        }
                        break;
                    case '巡逻':
                        // 巡逻行为 - 在区域内有目标地移动
                        // 当接近目标点或没有目标点时，选择新的目标点
                        if (!monster.targetX || !monster.targetY || 
                            (Math.abs(monster.x - monster.targetX) < 25 && Math.abs(monster.y - monster.targetY) < 25)) {
                            // 使用改进的分散式目标选择，避免聚集到中心
                            // 生成新的巡逻目标点，确保目标点在合理范围内
                            let newTargetX = this.generateScatteredPosition(this.gameAreaWidth, 50).x;
                            let newTargetY = this.generateScatteredPosition(this.gameAreaHeight, 50).y;
                            
                            // 确保目标点不会太靠近边界
                            newTargetX = Math.max(30, Math.min(this.gameAreaWidth - 30, newTargetX));
                            newTargetY = Math.max(30, Math.min(this.gameAreaHeight - 30, newTargetY));
                            
                            monster.targetX = newTargetX;
                            monster.targetY = newTargetY;
                        }
                        break;
                    case '守护':
                        // 守护行为 - 在固定点附近活动
                        // 在指定区域内小范围移动，不会远离守护点
                        // 初始化守护点为当前位置
                        if (!monster.guardX) {
                            monster.guardX = monster.x;
                            monster.guardY = monster.y;
                        }
                        // 计算与守护点的距离
                        const guardDistance = Math.sqrt((monster.x - monster.guardX) ** 2 + (monster.y - monster.guardY) ** 2);
                        // 如果距离守护点太远，设置目标返回守护点
                        if (guardDistance > 50) {
                            monster.targetX = monster.guardX;
                            monster.targetY = monster.guardY;
                        }
                        break;
                    case '狂暴':
                        // 狂暴行为 - 移动速度提升
                        // 永久性地提升移动速度（每次调用都会增加，但实际游戏中只调用一次）
                        monster.speed *= 1.5; // 狂暴状态下移动更快（提高到1.5倍）
                        break;
                    case '群体':
                        // 群体行为 - 与其他怪物协同行动
                        // 群体怪物会相互靠近，形成集群效应
                        // 查找附近的同类怪物
                        const nearbyMonsters = this.monsters.filter(m => {
                            if (m.id === monster.id) return false; // 排除自己
                            // 只考虑活跃的怪物
                            if (m.state === 'dead') return false;
                            const dx = m.x - monster.x;
                            const dy = m.y - monster.y;
                            // 计算距离，筛选150像素范围内的怪物（扩大范围）
                            return Math.sqrt(dx * dx + dy * dy) < 150;
                        });
                        // 如果附近有其他怪物，跟随中心点而不是单个怪物
                        if (nearbyMonsters.length > 0) {
                            // 计算群体中心点
                            let centerX = monster.x;
                            let centerY = monster.y;
                            nearbyMonsters.forEach(m => {
                                centerX += m.x;
                                centerY += m.y;
                            });
                            centerX /= (nearbyMonsters.length + 1);
                            centerY /= (nearbyMonsters.length + 1);
                            
                            // 设置目标为群体中心点
                            monster.targetX = centerX;
                            monster.targetY = centerY;
                        }
                        break;
                }
            }
            
            /**
             * 更新怪物移动 - 怪物运动系统的核心方法
             * 根据怪物的当前状态和行为模式计算新的位置
             * 实现了多种移动方式以适应不同的行为需求
             * 
             * 移动方式：
             * 1. 追击移动 - 直接朝目标点移动
             * 2. 巡逻移动 - 朝巡逻目标点移动（较慢速度）
             * 3. 随机移动 - 按方向向量移动（基础移动）
             * 
             * @param {Object} monster - 怪物对象，包含位置、状态和行为信息
             * @param {number} deltaTime - 时间差值（毫秒），用于计算移动距离
             */
            /**
             * 更新怪物移动 - 怪物移动系统
             * 根据怪物的状态、目标位置和速度更新其坐标位置
             * 实现平滑的移动动画效果和多种移动模式
             * 支持追击、巡逻和随机移动三种模式
             * 
             * 移动机制：
             * 1. 计算基于帧率的时间差值速度
             * 2. 根据怪物状态选择移动模式
             * 3. 向量计算实现精确移动
             * 4. 距离判断避免过度移动
             * 5. 随机扰动增加自然性
             * 
             * 追击状态移动特点：
             * - 高优先级移动模式
             * - 直接朝目标点快速移动
             * - 5像素接近阈值确保精确
             * - 适用于战斗追击场景
             * - 全速移动不减速
             * 
             * 巡逻状态移动特点：
             * - 中等优先级移动模式
             * - 朝巡逻目标点移动
             * - 速度减半显得悠闲自然
             * - 10像素接近阈值避免抖动
             * - 适用于非战斗状态
             * 
             * 随机移动特点：
             * - 默认基础移动模式
             * - 按方向向量持续移动
             * - 2%概率随机改变方向
             * - 模拟自然游荡行为
             * - 保持移动连续性
             * 
             * 时间差值处理：
             * - 基于16ms标准帧时间计算
             * - 保证不同帧率下移动速度一致
             * - 提升游戏体验流畅度
             * - 避免帧率影响平衡性
             * 
             * 向量移动原理：
             * - 计算目标点方向向量
             * - 标准化向量保证匀速
             * - 按速度缩放实现平滑
             * - 分别更新X和Y坐标
             * 
             * @param {Object} monster - 怪物对象，包含位置、状态和移动信息
             * @param {number} deltaTime - 时间差值（毫秒），用于时间相关计算
             */
            updateMonsterMovement(monster, deltaTime) {
                // 计算移动速度 - 基于怪物速度属性和时间差值
                // deltaTime/16是为了适配60FPS的标准帧率
                let moveSpeed = (monster.speed || 1) * (deltaTime / 16);
                
                // 追击状态移动 - 直接朝目标点移动
                if (monster.state === 'chase' && monster.targetX !== null) {
                    // 计算到目标点的向量和距离
                    const dx = monster.targetX - monster.x;
                    const dy = monster.targetY - monster.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    // 如果距离目标点还有一定距离，则继续移动
                    if (distance > 5) {
                        // 标准化向量并按速度移动
                        monster.x += (dx / distance) * moveSpeed;
                        monster.y += (dy / distance) * moveSpeed;
                    }
                } 
                // 巡逻状态移动 - 朝巡逻目标点移动（较慢速度）
                else if (monster.state === 'patrol' && monster.behavior === '巡逻' && monster.targetX) {
                    // 计算到巡逻目标点的向量和距离
                    const dx = monster.targetX - monster.x;
                    const dy = monster.targetY - monster.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    // 如果距离目标点还有一定距离，则继续移动
                    if (distance > 10) {
                        // 巡逻移动速度减半，显得更加悠闲
                        monster.x += (dx / distance) * moveSpeed * 0.7; // 提高到70%速度
                        monster.y += (dy / distance) * moveSpeed * 0.7;
                    }
                } 
                // 随机移动 - 按方向向量移动（基础移动方式）
                else {
                    // 随机改变方向，增加移动的自然性
                    if (Math.random() < 0.03) { // 增加转向频率
                        monster.direction = Math.random() * Math.PI * 2; // 随机方向（弧度）
                    }
                    
                    // 按当前方向向量移动
                    monster.x += Math.cos(monster.direction) * moveSpeed;
                    monster.y += Math.sin(monster.direction) * moveSpeed;
                }
            }
            
            /**
             * 检查怪物边界 - 怪物位置约束系统
             * 确保怪物不会移出游戏区域，处理边界碰撞和反弹
             * 采用物理反弹模型，使怪物移动更加自然
             * 
             * 边界处理机制：
             * 1. 边界检测 - 检查是否超出游戏区域
             * 2. 物理反弹 - 计算正确的反弹角度
             * 3. 随机扰动 - 避免规律性运动
             * 4. 自然转向 - 增加移动的随机性
             * 
             * @param {Object} monster - 怪物对象，包含位置和方向信息
             */
            /**
             * 检查怪物边界 - 怪物位置约束系统
             * 确保怪物不会移出游戏区域，处理边界碰撞和反弹
             * 采用物理反弹模型，使怪物移动更加自然
             * 支持精确的边界检测和智能反弹处理
             * 
             * 边界处理机制：
             * 1. 边界检测 - 检查是否超出游戏区域
             * 2. 物理反弹 - 计算正确的反弹角度
             * 3. 随机扰动 - 避免规律性运动
             * 4. 自然转向 - 增加移动的随机性
             * 5. 角度标准化 - 保持方向角度有效
             * 
             * 边界检测特点：
             * - 30像素边界边距避免贴边
             * - X轴和Y轴独立检测处理
             * - 精确位置重置防止越界
             * - 向心聚集问题修复
             * - 全方位边界保护
             * 
             * 物理反弹原理：
             * - 水平反弹：保持Y方向，反转X方向
             * - 垂直反弹：保持X方向，反转Y方向
             * - 角度计算确保反弹方向正确
             * - 反弹后角度范围标准化
             * - 反弹标记避免重复处理
             * 
             * 随机扰动机制：
             * - 反弹后添加小幅度角度扰动
             * - 扰动幅度π/8避免过度偏离
             * - 频率控制避免过度随机
             * - 角度标准化保持有效性
             * - 增强行为自然性
             * 
             * 自然转向机制：
             * - 0.3%低频随机转向
             * - 转向幅度π/6保持连贯性
             * - 避免过于规律的行为模式
             * - 增加移动路径多样性
             * - 模拟真实生物行为
             * 
             * 角度标准化处理：
             * - 保持角度在0-2π范围内
             * - 负角度自动转换为正角度
             * - 超过2π角度自动减去2π
             * - 确保数学计算准确性
             * - 避免角度累积误差
             * 
             * @param {Object} monster - 怪物对象，包含位置和方向信息
             */
            checkMonsterBounds(monster) {
                // 设置边界边距，避免怪物贴边
                const margin = 30;
                // 标记是否发生了反弹
                let bounced = false;
                
                // X轴边界检测 - 修复向心聚集问题
                // 左边界检测
                if (monster.x < margin) {
                    monster.x = margin; // 重置位置到边界
                    // 正确的水平反弹：保持Y方向，反转X方向
                    const currentAngle = monster.direction;
                    monster.direction = Math.PI - currentAngle;
                    // 确保反弹后角度指向右侧（0到PI之间）
                    if (monster.direction < 0) monster.direction += 2 * Math.PI;
                    if (monster.direction > Math.PI) monster.direction = Math.PI - (monster.direction - Math.PI);
                    bounced = true; // 标记发生了反弹
                } 
                // 右边界检测
                else if (monster.x > this.gameAreaWidth - margin) {
                    monster.x = this.gameAreaWidth - margin; // 重置位置到边界
                    // 正确的水平反弹：保持Y方向，反转X方向
                    const currentAngle = monster.direction;
                    monster.direction = Math.PI - currentAngle;
                    // 确保反弹后角度指向左侧（PI到2PI之间）
                    if (monster.direction < 0) monster.direction += 2 * Math.PI;
                    if (monster.direction < Math.PI) monster.direction = Math.PI + (Math.PI - monster.direction);
                    bounced = true; // 标记发生了反弹
                }
                
                // Y轴边界检测 - 修复向心聚集问题
                // 上边界检测
                if (monster.y < margin) {
                    monster.y = margin; // 重置位置到边界
                    // 正确的垂直反弹：保持X方向，反转Y方向
                    monster.direction = 2 * Math.PI - monster.direction;
                    if (monster.direction >= 2 * Math.PI) monster.direction -= 2 * Math.PI;
                    bounced = true; // 标记发生了反弹
                } 
                // 下边界检测
                else if (monster.y > this.gameAreaHeight - margin) {
                    monster.y = this.gameAreaHeight - margin; // 重置位置到边界
                    // 正确的垂直反弹：保持X方向，反转Y方向
                    monster.direction = 2 * Math.PI - monster.direction;
                    if (monster.direction >= 2 * Math.PI) monster.direction -= 2 * Math.PI;
                    bounced = true; // 标记发生了反弹
                }
                
                // 反弹后添加随机扰动，避免规律性运动
                // 使怪物的反弹行为更加自然，不会形成固定的循环路径
                if (bounced) {
                    monster.direction += (Math.random() - 0.5) * Math.PI / 8; // 减少扰动幅度
                    // 确保角度在0-2PI范围内
                    if (monster.direction < 0) monster.direction += 2 * Math.PI;
                    if (monster.direction >= 2 * Math.PI) monster.direction -= 2 * Math.PI;
                }
                
                // 随机转向，让怪物移动更自然但频率降低
                // 增加移动的随机性，避免过于规律的行为模式
                if (Math.random() < 0.003) { // 降低随机转向频率，避免过度随机
                    monster.direction += (Math.random() - 0.5) * Math.PI / 6;
                    // 确保角度在0-2PI范围内
                    if (monster.direction < 0) monster.direction += 2 * Math.PI;
                    if (monster.direction >= 2 * Math.PI) monster.direction -= 2 * Math.PI;
                }
            }

            /**
             * 更新建筑收入 - 改进版本
             * 添加金币安全检查和更平衡的收入计算
             * @param {number} deltaTime - 时间增量
             */
            /**
             * 更新建筑系统方法
             * 定期计算并发放建筑收入，应用各种加成效果
             * @param {number} deltaTime - 距离上一帧的时间差（毫秒）
             */
            /**
             * 更新建筑系统 - 经济系统
             * 定期计算并发放建筑收入
             * 应用各种加成效果并更新村庄金币
             * 提供收入反馈通知
             * 
             * 收入计算流程：
             * 1. 每10秒触发一次收入计算
             * 2. 遍历所有建筑对象
             * 3. 计算基础收入(等级×基础值)
             * 4. 应用称号加成效果
             * 5. 应用研究加成效果
             * 6. 确保收入为正值
             * 7. 累计总收入并更新金币
             * 8. 显示收入通知消息
             * 
             * 加成系统：
             * - 称号加成：建筑收入百分比提升
             * - 研究加成：经济增长研究额外收入
             * - 多重加成可叠加生效
             * - 向下取整保持数值整数
             * 
             * 数据安全：
             * - 防止负收入影响金币数量
             * - 确保金币不会变为负数
             * - 累计总收入用于用户反馈
             * - 时间间隔控制性能消耗
             * 
             * 用户体验：
             * - 定期收入通知提醒
             * - 明确显示收入金额
             * - 频率控制避免通知过多
             * - 收入为0时不显示通知
             * 
             * @param {number} deltaTime - 距离上次更新的时间差(毫秒)
             */
            updateBuildings(deltaTime) {
                // 根据用户要求，关闭自动产生金币的功能
                // 建筑收入现在通过冒险者交互产生，而不是自动产生
                // 每10秒更新一次建筑收入（降低频率以提高性能）
                if (this.gameTime % 10000 < deltaTime) {
                    let totalIncome = 0;
                    let totalMaintenance = 0; // 维护费用
                    // 使用for循环替代forEach以提高性能
                    for (let i = this.buildings.length - 1; i >= 0; i--) {
                        const building = this.buildings[i];
                        // 基于冒险者交互计算收入
                        let income = building.interactionIncome || 0;

                        // 应用称号加成 - 如果有建筑收入加成则应用
                        if (this.titleEffects.buildingIncome) {
                            income = Math.floor(income * (1 + this.titleEffects.buildingIncome));
                        }
                        
                        // 应用研究效果加成 - 经济增长研究提供额外收入
                        if (this.researchEffects.incomeBonus) {
                            income = Math.floor(income * (1 + this.researchEffects.incomeBonus));
                        }
                        
                        // 确保收入为正值，防止出现负收入
                        income = Math.max(0, income);
                        
                        // 计算维护费用（收入的5%）
                        const maintenance = Math.floor(income * 0.05);
                        totalMaintenance += maintenance;

                        // 安全添加金币 - 确保金币数量不会变为负数
                        // 根据用户要求，收入基于冒险者交互产生
                        this.gold = Math.max(0, this.gold + income);
                        // 累计总收入用于显示
                        totalIncome += income;
                        
                        // 重置交互收入计数器
                        building.interactionIncome = 0;
                    }

                    // 如果有收入则显示通知
                    if (totalIncome > 0) {
                        this.showNotification(`建筑收入: +${totalIncome}金 (维护费用: ${totalMaintenance}金)`);
                    } else if (totalMaintenance > 0) {
                        this.showNotification(`建筑维护费用: -${totalMaintenance}金`);
                    }
                }
            }

            /**
             * 处理建筑交互收入
             * 当冒险者使用建筑时调用此函数，增加建筑的交互计数和收入
             * @param {Object} building - 建筑对象
             * @param {number} income - 本次交互产生的收入
             */
            processBuildingInteraction(building, income) {
                // 增加交互计数
                building.interactionCount = (building.interactionCount || 0) + 1;
                
                // 累计交互收入
                building.interactionIncome = (building.interactionIncome || 0) + income;
                
                // 添加视觉效果
                const buildingElement = document.querySelector(`.building[data-id="${building.id}"]`);
                if (buildingElement) {
                    buildingElement.classList.add('interacted');
                    setTimeout(() => {
                        buildingElement.classList.remove('interacted');
                    }, 500);
                }
                
                // 根据建筑类型添加特殊效果
                switch(building.type) {
                    case '旅馆':
                        // 旅馆交互可能提高冒险者满意度
                        break;
                    case '饭店':
                        // 饭店交互可能提高冒险者满意度
                        break;
                    case '武器店':
                    case '防具店':
                        // 商店交互可能提高商店声誉
                        break;
                    case '魔法塔':
                        // 魔法塔交互可能提高魔法研究进度
                        break;
                    case '铁匠铺':
                        // 铁匠铺交互可能提高工艺技术
                        break;
                    case '炼金术师':
                        // 炼金术师交互可能提高炼金技术
                        break;
                    case '图书馆':
                        // 图书馆交互可能提高知识水平
                        break;
                    case '精灵树':
                        // 精灵树交互可能提高自然和谐度
                        break;
                    case '竞技场':
                        // 竞技场交互可能提高战斗技巧
                        break;
                    case '寺庙':
                        // 寺庙交互可能提高精神力
                        break;
                    default:
                        // 其他建筑类型
                        break;
                }
            }

            /**
             * 检查冒险者等级提升
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 检查冒险者等级提升 - 角色成长系统
             * 验证冒险者经验值是否达到升级条件
             * 满足条件时触发升级流程
             * 简化升级判断逻辑
             * 
             * 检查流程：
             * 1. 比较当前经验值与升级所需经验
             * 2. 如经验值充足则执行升级操作
             * 3. 调用具体升级方法处理属性提升
             * 4. 完成升级检查流程
             * 
             * 升级条件：
             * - 当前经验值大于等于最大经验值
             * - 支持连续升级(多次调用)
             * - 简化判断逻辑提高性能
             * - 作为升级入口统一管理
             * 
             * 系统集成：
             * - 与经验值获取系统联动
             * - 连接具体升级实现方法
             * - 支持各种升级触发场景
             * - 维护升级逻辑一致性
             * 
             * @param {Object} adventurer - 要检查升级的冒险者对象
             */
            checkAdventurerLevelUp(adventurer) {
                if (adventurer.exp >= adventurer.maxExp) {
                    this.levelUpAdventurer(adventurer);
                }
            }
            
            /**
             * 冒险者等级提升 - 角色成长系统
             * 执行冒险者升级的具体属性提升
             * 计算新的经验值需求并处理连续升级
             * 根据职业特性提供差异化成长
             * 
             * 升级流程：
             * 1. 增加冒险者等级
             * 2. 扣除升级消耗的经验值
             * 3. 计算下一级所需经验值(1.5倍递增)
             * 4. 根据职业成长属性提升基础属性
             * 5. 随机增加属性点增强游戏性
             * 6. 每5级提升暴击属性
             * 7. 记录升级日志信息
             * 8. 检查是否满足连续升级条件
             * 
             * 属性成长：
             * - 生命值：职业成长+随机(0-3)
             * - 魔法值：职业成长+随机(0-2)
             * - 攻击力：职业成长+随机(0-2)
             * - 防御力：职业成长+随机(0-1.5)
             * - 速度：职业成长+概率性增长
             * - 暴击：每5级固定提升
             * 
             * 连续升级：
             * - 自动检查剩余经验值
             * - 支持一次战斗多次升级
             * - 递归调用处理多级提升
             * - 避免经验值溢出浪费
             * 
             * 用户反馈：
             * - 实时记录升级时间戳
             * - 明确显示新等级数值
             * - 属性变化即时生效
             * - 支持连续升级通知
             * 
             * @param {Object} adventurer - 要升级的冒险者对象
             */
            levelUpAdventurer(adventurer) {
                adventurer.level++;
                adventurer.exp -= adventurer.maxExp;
                adventurer.maxExp = Math.floor(adventurer.maxExp * 1.5);

                // 根据职业成长属性升级
                const growth = adventurer.growth;
                adventurer.maxHp += Math.floor(growth.hp + Math.random() * 3);
                adventurer.hp = adventurer.maxHp;
                adventurer.maxMp += Math.floor(growth.mp + Math.random() * 2);
                adventurer.mp = adventurer.maxMp;
                adventurer.attack += Math.floor(growth.attack + Math.random() * 2);
                adventurer.defense += Math.floor(growth.defense + Math.random() * 1.5);
                adventurer.speed += growth.speed + (Math.random() > 0.7 ? 1 : 0);

                // 每5级增加暴击属性
                if (adventurer.level % 5 === 0) {
                    adventurer.critRate += 0.01;
                    adventurer.critDamage += 0.1;
                }

                adventurer.log.push(`${new Date().toLocaleTimeString()} 升级到${adventurer.level}级！`);

                if (adventurer.exp >= adventurer.maxExp) {
                    this.levelUpAdventurer(adventurer);
                }

                // 升级后立即更新实力评分，保证副本匹配/展示使用最新数据
                try {
                    this.calculateAdventurerPowerScore(adventurer);
                } catch (e) {
                    this.debugLog('levelUpAdventurer -> calculateAdventurerPowerScore 异常', e);
                }
            }

            /**
             * 检查并应用套装加成 - 装备系统
             * 统计冒险者装备的套装件数
             * 根据套装配置应用属性加成
             * 支持多套装和部分套装加成
             * 
             * 套装统计流程：
             * 1. 遍历冒险者所有装备部位
             * 2. 收集有套装属性的装备
             * 3. 按套装名称分类计数
             * 4. 去除套装名称前缀标准化
             * 5. 构建套装件数统计对象
             * 
             * 加成应用流程：
             * 1. 遍历所有套装统计结果
             * 2. 获取套装配置信息
             * 3. 验证套装件数是否满足条件(≥2)
             * 4. 计算加成倍率(当前件数/总件数)
             * 5. 根据配置应用各项属性加成
             * 6. 支持攻击、防御、生命、魔法加成
             * 
             * 套装系统：
             * - 支持多套装备同时生效
             * - 部分套装提供比例加成
             * - 配置化管理套装效果
             * - 动态计算加成数值
             * 
             * 数据处理：
             * - 套装名称标准化处理
             * - 件数统计准确无误
             * - 加成倍率范围控制
             * - 属性加成累加计算
             * 
             * @param {Object} adventurer - 要检查套装加成的冒险者对象
             */
            /**
             * 检查套装加成 - 装备系统
             * 检查冒险者当前装备的套装组合并应用相应属性加成
             * 支持多套装混搭和部分套装加成
             * 提升装备收集和搭配的策略深度
             * 
             * 套装检测机制：
             * 1. 遍历所有装备槽位
             * 2. 统计各套装的装备件数
             * 3. 移除套装前缀便于匹配
             * 4. 建立套装计数字典
             * 
             * 加成应用规则：
             * 1. 至少2件同套装装备才能激活加成
             * 2. 根据实际件数计算加成倍率
             * 3. 加成倍率 = min(实际件数/套装总件数, 1)
             * 4. 支持攻击、防御、生命、魔法等属性加成
             * 
             * 套装系统设计：
             * - 套装名称标准化处理（移除"套装："前缀）
             * - 支持不同套装混搭装备
             * - 部分套装加成提供渐进式收益
             * - 加成属性类型多样化
             * 
             * 加成计算机制：
             * - 基础加成 = 套装配置加成值
             * - 实际加成 = 基础加成 × 加成倍率
             * - 加成倍率上限为1.0避免溢出
             * - 支持多种属性同时加成
             * 
             * 应用场景：
             * - 装备更换后属性更新
             * - 战斗前属性计算
             * - 装备优化决策支持
             * - 套装收集进度追踪
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            checkSetBonuses(adventurer) {
                const setCounts = {};

                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    if (equipment && equipment.set) {
                        const setName = equipment.set.replace('套装：', '');
                        setCounts[setName] = (setCounts[setName] || 0) + 1;
                    }
                }

                // 应用套装加成
                for (const setName in setCounts) {
                    const count = setCounts[setName];
                    const setBonus = Config.EQUIPMENT_SETS[setName];

                    if (setBonus && count >= 2) {
                        // 根据套装件数应用不同加成
                        const bonusMultiplier = Math.min(count / setBonus.pieces, 1);

                        if (setBonus.bonus.attack) {
                            adventurer.attack += setBonus.bonus.attack * bonusMultiplier;
                        }
                        if (setBonus.bonus.defense) {
                            adventurer.defense += setBonus.bonus.defense * bonusMultiplier;
                        }
                        if (setBonus.bonus.hp) {
                            adventurer.maxHp += setBonus.bonus.hp * bonusMultiplier;
                        }
                        if (setBonus.bonus.mp) {
                            adventurer.maxMp += setBonus.bonus.mp * bonusMultiplier;
                        }
                    }
                }
            }

            /**
             * 向游戏日志添加条目
             * @param {string} message - 要添加的日志消息
             * @param {string} type - 日志类型 ('info', 'success', 'warning', 'error')
             */
            /**
             * 添加日志条目方法
             * 向游戏日志区域添加新的日志条目，并根据类型应用不同的样式
             * @param {string} message - 日志消息内容
             * @param {string} type - 日志类型（info/success/warning/error）
             */
            addLogEntry(message, type = 'info') {
                // 获取日志内容容器元素
                const logContent = document.getElementById('log-content');
                if (logContent) {
                    // 创建新的日志条目元素
                    const logEntry = document.createElement('p');
                    // 设置日志内容，包含时间戳
                    logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
                    
                    // 根据日志类型添加不同的样式
                    switch(type) {
                        case 'success':
                            logEntry.style.borderLeftColor = '#2ecc71';  // 绿色左边框
                            logEntry.style.background = 'rgba(46, 204, 113, 0.2)';  // 绿色背景
                            break;
                        case 'warning':
                            logEntry.style.borderLeftColor = '#f39c12';  // 橙色左边框
                            logEntry.style.background = 'rgba(243, 156, 18, 0.2)';  // 橙色背景
                            break;
                        case 'error':
                            logEntry.style.borderLeftColor = '#e74c3c';  // 红色左边框
                            logEntry.style.background = 'rgba(231, 76, 60, 0.2)';  // 红色背景
                            break;
                        default:
                            logEntry.style.borderLeftColor = '#3498db';  // 蓝色左边框
                            logEntry.style.background = 'rgba(52, 73, 94, 0.3)';  // 蓝色背景
                    }
                    
                    // 将日志条目添加到日志容器中
                    logContent.appendChild(logEntry);
                    
                    // 自动滚动到底部，确保最新日志可见
                    logContent.scrollTop = logContent.scrollHeight;
                    
                    // 限制日志数量，避免过多占用内存（最多保留50条日志）
                    const logEntries = logContent.querySelectorAll('p');
                    if (logEntries.length > 50) {
                        // 异步移除多余的日志条目，避免阻塞主线程
                        // 使用requestIdleCallback在空闲时间处理，如果没有则使用setTimeout
                        if (window.requestIdleCallback) {
                            requestIdleCallback(() => {
                                const currentEntries = logContent.querySelectorAll('p');
                                // 限制每次删除的数量，避免长时间阻塞
                                let removedCount = 0;
                                const maxRemovePerCall = 10;
                                while (currentEntries.length > 50 && removedCount < maxRemovePerCall) {
                                    currentEntries[0].remove();
                                    removedCount++;
                                }
                            });
                        } else {
                            setTimeout(() => {
                                const currentEntries = logContent.querySelectorAll('p');
                                // 限制每次删除的数量，避免长时间阻塞
                                let removedCount = 0;
                                const maxRemovePerCall = 10;
                                while (currentEntries.length > 50 && removedCount < maxRemovePerCall) {
                                    currentEntries[0].remove();
                                    removedCount++;
                                }
                            }, 0);
                        }
                    }
                }
            }

            /**
             * 更新UI方法
             * 统一更新游戏界面中的各种显示元素
             */
            updateUI() {
                // 更新资源显示（金币、魅力值等）
                this.updateResourceDisplay();
                // 更新冒险者列表显示
                this.updateAdventurerList();
                
                // 尝试更新存在的元素，如果不存在则跳过（兼容性处理）
                const monsterCountElement = document.getElementById('monster-count');
                if (monsterCountElement) {
                    monsterCountElement.textContent = this.monsters.length;
                }
                
                const monstersDefeatedElement = document.getElementById('monsters-defeated');
                if (monstersDefeatedElement) {
                    monstersDefeatedElement.textContent = this.monstersDefeated;
                }
                
                const equipmentFoundElement = document.getElementById('equipment-found');
                if (equipmentFoundElement) {
                    equipmentFoundElement.textContent = this.equipmentFound;
                }
                
                const taxRevenueElement = document.getElementById('tax-revenue');
                if (taxRevenueElement) {
                    taxRevenueElement.textContent = this.taxRevenue;
                }
            }

            /**
             * 更新文字游戏显示
             * 替代原有的Canvas渲染逻辑
             * 负责更新游戏界面中的各种状态信息显示
             */
            updateTextGameDisplay() {
                // 更新游戏状态显示 - 获取并更新各个状态显示元素
                const statusAdventurers = document.getElementById('status-adventurers'); // 冒险者数量
                const statusMonsters = document.getElementById('status-monsters');       // 怪物数量
                const statusBuildings = document.getElementById('status-buildings');     // 建筑数量
                const statusGold = document.getElementById('status-gold');               // 金币数量
                const statusCharm = document.getElementById('status-charm');             // 魅力值
                const statusDefeated = document.getElementById('status-defeated');       // 击败怪物数
                const statusEquipment = document.getElementById('status-equipment');     // 获得装备数
                const statusTax = document.getElementById('status-tax');                 // 税收收入
                const statusTime = document.getElementById('status-time');               // 游戏时间
                
                // 安全更新各个状态显示元素的文本内容
                if (statusAdventurers) statusAdventurers.textContent = this.adventurers.length;
                if (statusMonsters) statusMonsters.textContent = this.monsters.length;
                if (statusBuildings) statusBuildings.textContent = this.buildings.length;
                if (statusGold) statusGold.textContent = Math.floor(this.gold);
                if (statusCharm) statusCharm.textContent = this.charm;
                if (statusDefeated) statusDefeated.textContent = this.monstersDefeated;
                if (statusEquipment) statusEquipment.textContent = this.equipmentFound;
                if (statusTax) statusTax.textContent = this.taxRevenue;
                if (statusTime) statusTime.textContent = Math.floor(this.gameTime / 1000);
                
                // 更新详细统计信息 - 显示更详细的游戏数据
                this.updateDetailedStats();
                
                // 更新UI显示 - 调用通用UI更新方法
                this.updateUI();
            }

            /**
             * 更新详细统计信息显示
             * 提供更详细的游戏数据统计
             */
            updateDetailedStats() {
                // 更新游戏界面中的详细统计信息
                const detailedStats = document.getElementById('detailed-stats');
                if (detailedStats) {
                    // 计算统计数据
                    const activeAdventurers = this.adventurers.filter(a => a.state !== 'dead').length;
                    const deadAdventurers = this.adventurers.filter(a => a.state === 'dead').length;
                    const avgAdventurerLevel = this.adventurers.length > 0 ? 
                        (this.adventurers.reduce((sum, a) => sum + a.level, 0) / this.adventurers.length).toFixed(1) : 0;
                    
                    const normalMonsters = this.monsters.filter(m => m.rank === '普通').length;
                    const eliteMonsters = this.monsters.filter(m => m.rank === '精英').length;
                    const bossMonsters = this.monsters.filter(m => m.rank === '首领' || m.rank === '传说' || m.rank === '神话').length;
                    
                    const totalBuildingLevels = this.buildings.reduce((sum, b) => sum + b.level, 0);
                    const avgBuildingLevel = this.buildings.length > 0 ? 
                        (totalBuildingLevels / this.buildings.length).toFixed(1) : 0;
                    
                    // 更新统计显示
                    detailedStats.innerHTML = `
                        <div class="stat-item">
                            <span>活跃冒险者</span>
                            <span class="stat-value">${activeAdventurers}</span>
                        </div>
                        <div class="stat-item">
                            <span>死亡冒险者</span>
                            <span class="stat-value">${deadAdventurers}</span>
                        </div>
                        <div class="stat-item">
                            <span>冒险者平均等级</span>
                            <span class="stat-value">${avgAdventurerLevel}</span>
                        </div>
                        <div class="stat-item">
                            <span>普通怪物</span>
                            <span class="stat-value">${normalMonsters}</span>
                        </div>
                        <div class="stat-item">
                            <span>精英怪物</span>
                            <span class="stat-value">${eliteMonsters}</span>
                        </div>
                        <div class="stat-item">
                            <span>首领怪物</span>
                            <span class="stat-value">${bossMonsters}</span>
                        </div>
                        <div class="stat-item">
                            <span>建筑总数</span>
                            <span class="stat-value">${this.buildings.length}</span>
                        </div>
                        <div class="stat-item">
                            <span>建筑平均等级</span>
                            <span class="stat-value">${avgBuildingLevel}</span>
                        </div>
                    `;
                }
            }

            /**
             * 获取冒险者职业颜色 - 职业可视化系统
             * 根据冒险者的职业返回对应的颜色代码，用于界面显示和区分
             * 不同职业使用不同的颜色，便于玩家快速识别冒险者类型
             * 
             * 颜色设计原则：
             * 1. 战士 - 红色系，象征力量和勇气
             * 2. 法师 - 蓝色系，象征智慧和魔法
             * 3. 弓箭手 - 绿色系，象征敏捷和自然
             * 4. 盗贼 - 黄色系，象征速度和隐秘
             * 5. 牧师 - 紫色系，象征神圣和治疗
             * 
             * @param {string} className - 冒险者职业名称
             * @returns {string} 对应的十六进制颜色代码
             */
            /**
             * 获取冒险者颜色 - 界面视觉系统
             * 根据冒险者职业返回对应的颜色代码，用于界面元素着色
             * 不同职业使用不同颜色便于区分和识别
             * 支持5种基础职业和默认颜色处理
             * 
             * 颜色设计原则：
             * 1. 战士 - 红色系(#e74c3c) - 体现力量和热血
             * 2. 法师 - 蓝色系(#3498db) - 体现智慧和冷静
             * 3. 弓箭手 - 绿色系(#2ecc71) - 体现敏捷和自然
             * 4. 盗贼 - 黄色系(#f1c40f) - 体现机敏和神秘
             * 5. 牧师 - 紫色系(#9b59b6) - 体现神圣和治愈
             * 6. 未知职业 - 白色系(#ffffff) - 默认容错处理
             * 
             * 颜色选择考虑：
             * - 高对比度确保可读性
             * - 色彩心理学匹配职业特性
             * - 与游戏整体配色协调
             * - 便于视觉快速识别区分
             * 
             * 应用场景：
             * - 冒险者列表职业标识
             * - 战斗界面角色标记
             * - 装备界面职业限制显示
             * - 统计图表职业分类着色
             * 
             * @param {string} className - 冒险者职业名称
             * @returns {string} 对应的十六进制颜色代码
             */
            getAdventurerColor(className) {
                switch(className) {
                    case '战士': return '#e74c3c';
                    case '法师': return '#3498db';
                    case '弓箭手': return '#2ecc71';
                    case '盗贼': return '#f1c40f';
                    case '牧师': return '#9b59b6';
                    default: return '#ffffff';
                }
            }

            /**
             * 自定义日志函数 - 控制台日志管理系统
             * 根据enableConsoleLog属性控制是否输出控制台日志
             * 用于替代直接调用console.log，便于统一控制日志输出
             * 
             * @param {...any} args - 日志参数，支持任意数量和类型的参数
             */
            debugLog(...args) {
                if (this.enableConsoleLog) {
                    console.log(...args);
                }
            }

            /**
             * 获取职业缩写 - 界面显示优化系统
             * 将完整的职业名称转换为单字符缩写，用于界面紧凑显示
             * 在空间有限的界面元素中使用缩写可以提高信息密度
             * 
             * 缩写设计原则：
             * 1. 使用职业名称的首个汉字，直观易懂
             * 2. 盗贼使用"贼"字，避免与战士职业混淆
             * 3. 未知职业返回问号，确保容错性
             * 
             * @param {string} className - 冒险者职业名称
             * @returns {string} 对应的单字符缩写
             */
            /**
             * 获取职业缩写 - 界面显示优化系统
             * 将完整的职业名称转换为单字符缩写，用于界面紧凑显示
             * 在空间有限的界面元素中使用缩写可以提高信息密度
             * 支持5种基础职业和默认未知处理
             * 
             * 缩写设计原则：
             * 1. 使用职业名称的首个汉字，直观易懂
             * 2. 盗贼使用"贼"字，避免与战士职业混淆
             * 3. 未知职业返回问号，确保容错性
             * 4. 所有缩写保持单字符长度
             * 5. 字符选择考虑辨识度和语义关联
             * 
             * 职业缩写映射：
             * - 战士 → 战 (体现战斗特性)
             * - 法师 → 法 (体现法术特性)
             * - 弓箭手 → 弓 (体现武器特性)
             * - 盗贼 → 贼 (体现职业特性)
             * - 牧师 → 牧 (体现治疗特性)
             * - 未知职业 → ? (容错处理标识)
             * 
             * 应用场景：
             * - 冒险者列表紧凑显示
             * - 战斗界面角色标识
             * - 装备界面职业限制标记
             * - 统计图表职业分类标识
             * - 状态栏简要信息显示
             * 
             * 设计优势：
             * - 节省显示空间提高信息密度
             * - 保持语义关联便于理解
             * - 统一长度便于界面布局
             * - 单字符处理简化逻辑
             * 
             * @param {string} className - 冒险者职业名称
             * @returns {string} 对应的单字符缩写
             */
            getClassAbbreviation(className) {
                switch(className) {
                    case '战士': return '战';
                    case '法师': return '法';
                    case '弓箭手': return '弓';
                    case '盗贼': return '贼';
                    case '牧师': return '牧';
                    default: return '?';
                }
            }

            /**
             * 减少装备耐久度 - 装备损耗系统
             * 在战斗或使用过程中减少冒险者装备的耐久度
             * 耐久度为0时装备失效，需要修理才能继续使用
             * 
             * 耐久度机制作用：
             * 1. 增加游戏策略性，需要定期维护装备
             * 2. 平衡游戏经济，促进修理和购买行为
             * 3. 增强装备价值感，高级装备更需保护
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {number} amount - 要减少的耐久度值
             */
            /**
             * 减少装备耐久度 - 装备损耗系统
             * 在战斗或使用过程中减少冒险者装备的耐久度
             * 耐久度为0时装备失效，需要修理才能继续使用
             * 支持批量处理所有装备槽位的耐久度减少
             * 
             * 耐久度机制作用：
             * 1. 增加游戏策略性，需要定期维护装备
             * 2. 平衡游戏经济，促进修理和购买行为
             * 3. 增加装备管理深度，提升游戏体验
             * 4. 避免装备永久性过强破坏平衡
             * 
             * 损耗处理特点：
             * - 遍历所有装备槽位统一处理
             * - 耐久度不会低于0确保数据安全
             * - 支持自定义损耗量参数化控制
             * - 无装备槽位自动跳过处理
             * 
             * 损耗计算机制：
             * - 新耐久度 = 原耐久度 - 损耗量
             * - 最小值限制为0避免负数
             * - Math.max确保不会低于下限
             * - 批量处理提高执行效率
             * 
             * 应用场景：
             * - 战斗结束后统一扣除耐久
             * - 特殊技能消耗装备耐久
             * - 时间流逝自然损耗
             * - 特殊环境加速损耗
             * 
             * @param {Object} adventurer - 冒险者对象
             * @param {number} amount - 耐久度减少量
             */
            reduceEquipmentDurability(adventurer, amount) {
                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    if (equipment) {
                        equipment.durability = Math.max(0, equipment.durability - amount);
                    }
                }
            }

            /**
             * 文字游戏渲染方法
             * 替代原有的Canvas渲染逻辑，更新文字界面
             * 这是文字版游戏的核心渲染方法，负责更新所有UI元素的显示
             */
            renderTextGame() {
                // 更新文字游戏显示
                // 调用专门的显示更新方法，保持代码结构清晰
                this.updateTextGameDisplay();
            }

            /**
             * 检查装备耐久度 - 装备维护提醒系统
             * 检查冒险者所有装备的耐久度，当耐久度过低时发出提醒
             * 帮助玩家及时维护装备，避免战斗中装备损坏
             * 
             * 检查机制：
             * 1. 遍历所有装备槽位
             * 2. 检查装备是否存在且耐久度低于阈值（20）
             * 3. 记录提醒日志
             * 
             * 设计考虑：
             * - 提前预警避免装备突然损坏
             * - 给玩家维护装备的时间
             * - 增加游戏策略性
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 检查装备耐久度 - 装备维护提醒系统
             * 检查冒险者所有装备的耐久度，当耐久度过低时发出提醒
             * 帮助玩家及时维护装备，避免战斗中装备损坏
             * 支持批量检查所有装备槽位的耐久度状态
             * 根据装备类型和重要性采用不同的检查阈值
             * 
             * 检查机制：
             * 1. 遍历所有装备槽位
             * 2. 根据装备类型采用不同的耐久度阈值
             * 3. 武器和防具：耐久度低于20%时提醒
             * 4. 饰品：耐久度低于10%时提醒
             * 5. 任何装备：耐久度低于5%时紧急提醒
             * 
             * 耐久度阈值设计：
             * - 武器/防具：耐久度低于20%需要关注
             * - 饰品：耐久度低于10%需要关注
             * - 任何装备：耐久度低于5%需要紧急处理
             * - 分级提醒避免信息过载
             * 
             * 提醒机制特点：
             * - 实时日志记录确保提醒可见
             * - 包含具体时间便于追踪
             * - 明确指出需要修理的装备
             * - 非阻断式提醒不影响游戏流程
             * - 根据紧急程度提供不同提醒
             * 
             * 应用场景：
             * - 冒险者日常状态检查
             * - 战斗前装备状态确认
             * - 装备维护计划制定参考
             * - 资源管理决策支持
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            checkEquipmentDurability(adventurer) {
                for (const slot in adventurer.equipment) {
                    const equipment = adventurer.equipment[slot];
                    if (!equipment) continue;
                    
                    // 计算耐久度比例
                    const durabilityRatio = equipment.durability / equipment.maxDurability;
                    
                    // 紧急情况提醒
                    if (durabilityRatio < 0.05) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}耐久度极低(${equipment.durability}/${equipment.maxDurability})，需要紧急修理！`);
                    }
                    // 武器和防具提醒
                    else if (['武器', '头盔', '胸甲', '护手', '护腿', '靴子'].includes(equipment.slot) && 
                             durabilityRatio < 0.2) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}耐久度较低(${equipment.durability}/${equipment.maxDurability})，建议修理`);
                    }
                    // 饰品提醒
                    else if (['戒指', '项链', '腰带', '护符'].includes(equipment.slot) && 
                             durabilityRatio < 0.1) {
                        adventurer.log.push(`${new Date().toLocaleTimeString()} ${equipment.name}耐久度偏低(${equipment.durability}/${equipment.maxDurability})，可以考虑修理`);
                    }
                }
            }

            /**
             * 自动装备更好物品 - 装备优化系统
             * 自动将背包中评分更高的装备装备到对应槽位
             * 提升冒险者战斗力，优化装备配置
             * 
             * 装备策略：
             * 1. 遍历背包中所有物品
             * 2. 比较当前装备与背包物品的评分
             * 3. 装备评分更高的物品
             * 4. 将被替换的装备放回背包
             * 5. 更新装备属性加成
             * 
             * 设计考虑：
             * - 使用评分系统确保装备选择合理性
             * - 自动化装备提升游戏体验
             * - 保持装备系统的平衡性
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 自动装备更好物品 - 装备优化系统
             * 自动将背包中评分更高的装备装备到对应槽位
             * 提升冒险者战斗力，优化装备配置
             * 支持智能装备替换和背包管理
             * 
             * 装备策略：
             * 1. 遍历背包中所有物品
             * 2. 比较当前装备与背包物品的评分
             * 3. 装备评分更高的物品
             * 4. 将被替换的装备放回背包
             * 5. 更新装备属性加成
             * 6. 记录装备操作日志
             * 
             * 装备比较机制：
             * - 使用calculateItemScore方法计算装备评分
             * - 无当前装备时直接装备
             * - 评分更高时执行替换
             * - 评分相同时保持现状
             * 
             * 装备替换流程：
             * - 被替换装备放入背包
             * - 新装备从背包移除并装备
             * - 更新背包物品列表过滤已装备物品
             * - 添加装备日志记录
             * - 重新计算装备属性加成
             * 
             * 设计考虑：
             * - 使用评分系统确保装备选择合理性
             * - 自动化装备提升游戏体验
             * - 保持装备系统的平衡性
             * - 避免装备丢失确保数据安全
             * - 实时更新属性确保准确性
             * 
             * 应用场景：
             * - 冒险者获得新装备后自动优化
             * - 战斗前装备状态检查和优化
             * - 装备系统智能化管理
             * - 玩家体验优化减少手动操作
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            autoEquipBetterItems(adventurer) {
                for (const item of adventurer.inventory) {
                    const currentEquip = adventurer.equipment[item.slot];

                    if (!currentEquip || this.calculateItemScore(item) > this.calculateItemScore(currentEquip)) {
                        if (currentEquip) {
                            adventurer.inventory.push(currentEquip);
                        }

                        adventurer.equipment[item.slot] = item;
                        adventurer.inventory = adventurer.inventory.filter(i => i.id !== item.id);
                        adventurer.log.push(`${new Date().toLocaleTimeString()} 自动装备了${item.name}`);

                        this.updateEquipmentBonuses(adventurer);
                    }
                }
            }

            /**
             * 计算装备评分 - 装备评估系统
             * 根据装备的各项属性计算综合评分，用于装备比较和自动装备
             * 评分系统确保冒险者能自动选择最优装备
             * 
             * 评分计算规则：
             * 1. 基础属性直接累加（攻击、防御、生命、魔法、速度）
             * 2. 暴击属性加权计算（暴击率×100，暴击伤害×50）
             * 3. 等级加成（等级×10）
             * 4. 稀有度倍数加成（根据稀有度索引计算）
             * 
             * 权重设计原则：
             * - 攻击和防御属性权重较高
             * - 暴击属性有特殊权重
             * - 稀有度对评分有显著影响
             * 
             * @param {Object} item - 装备对象
             * @returns {number} 装备综合评分
             */
            /**
             * 计算装备评分 - 装备评估系统
             * 综合评估装备的各项属性价值
             * 用于装备比较和自动装备决策
             * 支持不同稀有度装备的权重调整
             * 
             * 评分计算：
             * - 攻击力：1:1直接计入评分
             * - 防御力：1:1直接计入评分
             * - 生命值：1:1直接计入评分
             * - 魔法值：1:1直接计入评分
             * - 速度：1:1直接计入评分
             * - 暴击率：1:100换算后计入
             * - 暴击伤害：1:50换算后计入
             * - 装备等级：1:10换算后计入
             * 
             * 稀有度加成：
             * - 按照稀有度索引计算加成
             * - 稀有度越高加成越多
             * - 加成公式：基础评分×(1+稀有度索引×0.5)
             * - 保证高稀有度装备优先级
             * 
             * 权重设计：
             * - 暴击属性高权重体现价值
             * - 稀有度显著影响最终评分
             * - 等级提供基础评分保障
             * - 综合考虑所有属性平衡
             * 
             * 应用场景：
             * - 自动装备系统决策依据
             * - 装备排序和筛选标准
             * - 背包管理优化参考
             * - 装备价值量化评估
             * 
             * @param {Object} item - 装备对象
             * @returns {number} 装备综合评分
             */
            /**
             * 计算物品评分 - 装备评估系统
             * 综合评估装备的各项属性计算综合评分，用于装备比较和选择
             * 评分系统考虑了基础属性、稀有度等多个维度，确保评估准确性
             * 支持不同属性权重的差异化计算
             * 
             * 评分计算公式：
             * 基础评分 = 攻击力 + 防御力 + 生命值 + 魔法值 + 速度 + 暴击率×100 + 暴击伤害×50 + 等级×10
             * 稀有度加成 = 基础评分 × (1 + 稀有度索引 × 0.5)
             * 最终评分 = 基础评分 × 稀有度加成
             * 
             * 属性权重设计：
             * - 攻击力：1:1直接计入评分
             * - 防御力：1:1直接计入评分
             * - 生命值：1:1直接计入评分
             * - 魔法值：1:1直接计入评分
             * - 速度：1:1直接计入评分
             * - 暴击率：1:100高权重计入评分
             * - 暴击伤害：1:50中等权重计入评分
             * - 装备等级：1:10中等权重计入评分
             * 
             * 稀有度加成机制：
             * - 白色装备：无加成(1.0倍)
             * - 绿色装备：0.5倍加成(1.5倍)
             * - 蓝色装备：1.0倍加成(2.0倍)
             * - 紫色装备：1.5倍加成(2.5倍)
             * - 橙色装备：2.0倍加成(3.0倍)
             * - 红色装备：2.5倍加成(3.5倍)
             * - 粉色装备：3.0倍加成(4.0倍)
             * 
             * 评分应用场景：
             * - 装备自动替换决策
             * - 装备价值排序比较
             * - 背包物品优先级判断
             * - 装备推荐系统评估
             * 
             * @param {Object} item - 装备对象
             * @returns {number} 装备综合评分
             */
            calculateItemScore(item) {
                let score = 0;
                score += item.attack || 0;
                score += item.defense || 0;
                score += item.hp || 0;
                score += item.mp || 0;
                score += item.speed || 0;
                score += (item.critRate || 0) * 100;
                score += (item.critDamage || 0) * 50;
                score += item.level * 10;

                const rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(item.rarity);
                if (rarityIndex >= 0) {
                    score *= (1 + rarityIndex * 0.5);
                }

                return score;
            }

            /**
             * 出售多余物品 - 背包管理系统
             * 当冒险者背包物品超过容量限制时，自动出售低价值物品
             * 确保冒险者能继续获得新装备，避免背包溢出
             * 
             * 出售策略：
             * 1. 背包容量限制为20个物品
             * 2. 优先出售价值最低的物品
             * 3. 出售价格为物品价值的50%
             * 4. 循环出售直到背包空间足够
             * 
             * 设计考虑：
             * - 避免出售高价值装备
             * - 保持背包流动性
             * - 维持游戏经济平衡
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 出售多余物品 - 背包管理系统（调整版）
             * 当冒险者背包物品超过20件且评分低的装备，可以通过市场交易给别的需要的冒险者，
             * 也可以低价10%回收给系统，这个钱不从村庄界面扣除
             * 
             * 处理策略：
             * 1. 背包容量限制为20个物品
             * 2. 优先处理价值最低的物品
             * 3. 回收价格为物品价值的10%（低价回收）
             * 4. 每次最多处理3个物品，避免长时间阻塞
             * 5. 记录处理日志便于追踪
             * 
             * 设计考虑：
             * - 冒险者之间可以交易装备
             * - 低价值装备可以低价回收给系统
             * - 保持背包流动性确保游戏体验
             * - 维持游戏经济平衡
             * - 限制单次处理数量避免阻塞
             * - 日志记录提供操作反馈和追踪
             * 
             * 价值评估机制：
             * - 使用装备内置value属性作为评估标准
             * - 遍历所有物品找出最低价值项
             * - 精确定位最低价值物品索引
             * - 确保每次只处理一个最低价值物品
             * 
             * 经济处理流程：
             * - 回收价格 = 物品价值 × 10%（低价回收）
             * - 冒险者获得金币增加
             * - 物品从背包中移除
             * - 添加操作日志记录
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            sellExcessItems(adventurer) {
                // 限制单次处理物品数量，避免长时间阻塞
                let processedCount = 0;
                const maxProcessedPerCall = 3; // 减少单次处理数量
                while (adventurer.inventory.length > 20 && processedCount < maxProcessedPerCall) {
                    let lowestValueItem = adventurer.inventory[0];
                    let lowestValueIndex = 0;

                    for (let i = 1; i < adventurer.inventory.length; i++) {
                        if (adventurer.inventory[i].value < lowestValueItem.value) {
                            lowestValueItem = adventurer.inventory[i];
                            lowestValueIndex = i;
                        }
                    }

                    // 低价回收给系统（10%价格），这个钱不从村庄界面扣除
                    const recyclePrice = Math.floor(lowestValueItem.value * 0.1);
                    adventurer.gold += recyclePrice;
                    // 注意：这个钱不从村庄界面扣除，所以不减少this.gold

                    adventurer.inventory.splice(lowestValueIndex, 1);
                    processedCount++;
                    adventurer.log.push(`${new Date().toLocaleTimeString()} 回收${lowestValueItem.name}，获得${recyclePrice}金币`);
                }
            }

            /**
             * 更新装备属性加成 - 装备系统核心方法
             * 根据冒险者的装备重新计算所有属性值
             * 确保装备变化能正确反映在角色属性上
             * 
             * 属性计算流程：
             * 1. 重置到基础属性（职业基础值）
             * 2. 加上等级成长属性（随等级提升的属性）
             * 3. 加上装备属性（当前装备提供的属性加成）
             * 4. 应用高级装备额外加成（稀有装备特殊效果）
             * 5. 确保当前值不超过最大值（防止异常）
             * 
             * 属性类型：
             * - 攻击力：影响战斗伤害输出
             * - 防御力：减少受到的伤害
             * - 生命值：决定生存能力
             * - 魔法值：决定技能使用能力
             * - 速度：影响移动和行动顺序
             * - 暴击率：影响暴击触发概率
             * - 暴击伤害：影响暴击伤害倍数
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            /**
             * 更新装备属性加成 - 装备系统核心方法
             * 根据冒险者的装备重新计算所有属性值
             * 确保装备变化能正确反映在角色属性上
             * 支持职业基础属性、等级成长和装备加成的综合计算
             * 
             * 属性计算流程：
             * 1. 重置到基础属性（职业基础值）
             * 2. 加上等级成长属性（随等级提升的属性）
             * 3. 加上装备属性（当前装备提供的属性加成）
             * 4. 应用高级装备额外加成（稀有装备特殊效果）
             * 5. 确保当前值不超过最大值（防止异常）
             * 
             * 基础属性构成：
             * - 攻击力 = 10 + 职业攻击力
             * - 防御力 = 5 + 职业防御力
             * - 最大生命值 = 100 + 职业生命值
             * - 最大魔法值 = 50 + 职业魔法值
             * - 速度 = 5 + 职业速度
             * - 暴击率 = 0.05（5%基础暴击率）
             * - 暴击伤害 = 1.5（150%基础暴击伤害）
             * 
             * 等级成长机制：
             * - 2级开始计算成长属性
             * - 生命值：基础成长 + 随机值(0-3)
             * - 魔法值：基础成长 + 随机值(0-2)
             * - 攻击力：基础成长 + 随机值(0-2)
             * - 防御力：基础成长 + 随机值(0-1.5)
             * - 速度：基础成长 + 30%概率+1
             * - 每5级提升暴击属性（暴击率+1%，暴击伤害+10%）
             * 
             * 装备属性加成：
             * - 遍历所有装备槽位
             * - 累加装备提供的各项属性
             * - 支持攻击、防御、生命、魔法、速度、暴击等属性
             * - 无装备槽位自动跳过
             * 
             * 高级装备加成：
             * - 橙色及以上稀有度装备(索引>=4)
             * - 额外生命值加成 = 装备等级 × 0.5（取整）
             * - 额外速度加成 = 稀有度索引 ÷ 2（取整）
             * - 提升高稀有度装备价值
             * 
             * 数据安全机制：
             * - 当前生命值不超过最大生命值
             * - 当前魔法值不超过最大魔法值
             * - 防止属性异常导致游戏错误
             * 
             * @param {Object} adventurer - 冒险者对象
             */
            updateEquipmentBonuses(adventurer) {
                const classStats = Config.CLASSES[adventurer.class];
                const growth = adventurer.growth;

                // 重置到基础属性
                adventurer.attack = 10 + classStats.attack;
                adventurer.defense = 5 + classStats.defense;
                adventurer.maxHp = 100 + classStats.hp;
                adventurer.maxMp = 50 + classStats.mp;
                adventurer.speed = 5 + classStats.speed;
                adventurer.critRate = 0.05;
                adventurer.critDamage = 1.5;

                // 加上等级成长属性
                for (let i = 2; i <= adventurer.level; i++) {
                    adventurer.maxHp += Math.floor(growth.hp + Math.random() * 3);
                    adventurer.maxMp += Math.floor(growth.mp + Math.random() * 2);
                    adventurer.attack += Math.floor(growth.attack + Math.random() * 2);
                    adventurer.defense += Math.floor(growth.defense + Math.random() * 1.5);
                    adventurer.speed += growth.speed + (Math.random() > 0.7 ? 1 : 0);

                    if (i % 5 === 0) {
                        adventurer.critRate += 0.01;
                        adventurer.critDamage += 0.1;
                    }
                }

                // 加上装备属性
                for (const slot in adventurer.equipment) {
                    const item = adventurer.equipment[slot];
                    if (item) {
                        adventurer.attack += item.attack || 0;
                        adventurer.defense += item.defense || 0;
                        adventurer.maxHp += item.hp || 0;
                        adventurer.maxMp += item.mp || 0;
                        adventurer.speed += item.speed || 0;
                        adventurer.critRate += item.critRate || 0;
                        adventurer.critDamage += item.critDamage || 0;

                        // 高级装备额外加成
                        const rarityIndex = Config.EQUIPMENT_RARITIES.indexOf(item.rarity);
                        if (rarityIndex >= 4) {
                            adventurer.maxHp += Math.floor(item.level * 0.5);
                            adventurer.speed += Math.floor(rarityIndex / 2);
                        }
                    }
                }

                // 确保当前值不超过最大值
                adventurer.hp = Math.min(adventurer.hp, adventurer.maxHp);
                adventurer.mp = Math.min(adventurer.mp, adventurer.maxMp);

                // ===== 关键：在装备属性变动后，重新计算并更新冒险者的实力评分 =====
                // 这样可以保证 UI 和副本计算中使用的 powerScore 为最新值
                try {
                    this.calculateAdventurerPowerScore(adventurer);
                } catch (e) {
                    // 即使评分计算失败，也不影响核心流程，记录调试信息
                    this.debugLog('updateEquipmentBonuses -> calculateAdventurerPowerScore 异常', e);
                }
            }

            /**
             * 保存游戏方法
             * 将当前游戏状态序列化并保存到浏览器localStorage中
             */
            saveGame() {
                // 构建存档数据对象，包含游戏的所有重要状态
                const saveData = {
                    gold: this.gold,                    // 金币数量
                    charm: this.charm,                  // 魅力值
                    buildings: this.buildings,          // 建筑列表
                    adventurers: this.adventurers,      // 冒险者列表
                    gameTime: this.gameTime,            // 游戏运行时间
                    monstersDefeated: this.monstersDefeated,  // 击败怪物数量
                    equipmentFound: this.equipmentFound,      // 获得装备数量
                    taxRevenue: this.taxRevenue,              // 税收收入
                    totalTaxCollected: this.totalTaxCollected,// 总税收收入
                    currentTitle: this.currentTitle,          // 当前称号
                    unlockedTitles: this.unlockedTitles,      // 已解锁称号列表
                    titleEffects: this.titleEffects,          // 称号效果
                    lastTaxTime: this.lastTaxTime             // 上次税收时间
                };

                // 将存档数据序列化为JSON字符串并保存到localStorage
                localStorage.setItem('adventureVillageSave', JSON.stringify(saveData));
                // 显示保存成功通知
                this.showNotification('游戏已保存！');
                // 添加日志记录
                this.addLogEntry('游戏已保存', 'success');
            }

            /**
             * 加载游戏方法
             * 从浏览器localStorage中读取存档数据并恢复游戏状态
             */
            loadGame() {
                // 从localStorage中获取存档数据
                const saveData = localStorage.getItem('adventureVillageSave');
                if (saveData) {
                    try {
                        // 解析存档数据
                        const data = JSON.parse(saveData);

                        // 恢复游戏状态
                        this.gold = data.gold;                    // 恢复金币数量
                        this.charm = data.charm;                  // 恢复魅力值
                        this.buildings = data.buildings;          // 恢复建筑列表
                        this.adventurers = data.adventurers;      // 恢复冒险者列表
                        this.gameTime = data.gameTime;            // 恢复游戏运行时间
                        this.monstersDefeated = data.monstersDefeated || 0;     // 恢复击败怪物数量
                        this.equipmentFound = data.equipmentFound || 0;         // 恢复获得装备数量
                        this.taxRevenue = data.taxRevenue || 0;                 // 恢复税收收入
                        this.totalTaxCollected = data.totalTaxCollected || 0;   // 恢复总税收收入
                        this.currentTitle = data.currentTitle || '新手村长';    // 恢复当前称号
                        this.unlockedTitles = data.unlockedTitles || ['新手村长']; // 恢复已解锁称号列表
                        this.titleEffects = data.titleEffects || Config.TITLES['新手村长'].effects; // 恢复称号效果
                        this.lastTaxTime = data.lastTaxTime || 0;               // 恢复上次税收时间

                        // 更新界面显示
                        this.updateResourceDisplay();    // 更新资源显示
                        this.updateAdventurerList();     // 更新冒险者列表
                        this.updateUI();                 // 更新UI界面
                        this.updateTitleDisplay();       // 更新称号显示

                        // 显示加载成功通知
                        this.showNotification('游戏已加载！');
                        // 添加日志记录
                        this.addLogEntry('游戏已加载', 'success');
                    } catch (e) {
                        // 解析存档数据失败，显示错误通知
                        this.showNotification('加载游戏失败：存档数据损坏', 'error');
                        this.addLogEntry('加载游戏失败：存档数据损坏', 'error');
                    }
                } else {
                    // 没有找到存档数据，显示提示通知
                    this.showNotification('没有找到存档数据', 'error');
                }
            }
        }

        // 游戏初始化函数 - 在窗口加载后自动运行
        window.onload = function() {
            // 创建游戏实例
            const game = new Game();
            window.game = game; // 将游戏实例挂载到全局作用域，方便调试
            
            // 初始化后台运行相关属性
            game.backgroundUpdateActive = false;
            game.lastBackgroundUpdate = 0;
            
            // 移动端优化
            // 检测是否为移动设备
            const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
            
            // 如果是移动设备，添加特殊处理
            if (isMobile) {
                // 禁用双击缩放
                document.addEventListener('touchstart', function(e) {
                    if (e.touches.length > 1) {
                        e.preventDefault();
                    }
                }, { passive: false });
                
                // 防止双击缩放
                let lastTouchEnd = 0;
                document.addEventListener('touchend', function(e) {
                    const now = (new Date()).getTime();
                    if (now - lastTouchEnd <= 300) {
                        e.preventDefault();
                    }
                    lastTouchEnd = now;
                }, false);
            }
            
            // 监听页面可见性变化，优化后台运行
            document.addEventListener('visibilitychange', () => {
                game.debugLog('Visibility change detected in window.onload:', document.hidden ? 'hidden' : 'visible');
                if (document.hidden) {
                    // 页面隐藏时启动后台更新
                    if (!game.isPaused) {
                        game.debugLog('Starting background update in window.onload');
                        game.backgroundUpdateActive = true;
                        game.lastBackgroundUpdate = Date.now();
                        // 立即启动后台更新
                        setTimeout(() => {
                            if (game.backgroundUpdateActive) {
                                game.backgroundUpdate();
                            }
                        }, 100);
                    }
                } else {
                    // 页面显示时停止后台更新
                    game.debugLog('Stopping background update in window.onload');
                    game.backgroundUpdateActive = false;
                    // 确保主循环继续运行
                    if (game.mainLoopRunning) {
                        requestAnimationFrame(game.gameLoop.bind(game));
                    }
                }
            });
            
            // 监听窗口焦点变化，进一步优化后台运行
            window.addEventListener('blur', () => {
                game.debugLog('Window blur detected in window.onload');
                // 窗口失去焦点时启动后台更新
                if (!game.isPaused) {
                    game.debugLog('Starting background update on blur in window.onload');
                    game.backgroundUpdateActive = true;
                    game.lastBackgroundUpdate = Date.now();
                    // 立即启动后台更新
                    setTimeout(() => {
                        if (game.backgroundUpdateActive) {
                            game.backgroundUpdate();
                        }
                    }, 100);
                }
            });
            
            window.addEventListener('focus', () => {
                game.debugLog('Window focus detected in window.onload');
                // 窗口获得焦点时停止后台更新
                game.backgroundUpdateActive = false;
                // 确保主循环继续运行
                if (game.mainLoopRunning) {
                    requestAnimationFrame(game.gameLoop.bind(game));
                }
            });

            // 初始化时生成更多怪物，确保游戏开始就有怪物
            // 改为分批生成，避免阻塞主线程
            let initialMonsterCount = 0;
            const initialMonsters = 6; // 减少初始怪物数量
            const initialAdventurers = 2; // 减少初始冒险者数量
            
            // 分批生成初始怪物
            const createInitialMonsters = () => {
                if (initialMonsterCount < initialMonsters && game.monsters.length < Config.MONSTER_MAX_COUNT) {
                    const monster = game.createMonster();
                    if (monster) {
                        game.addLogEntry(`初始生成怪物: ${monster.rank}${monster.type} Lv.${monster.level}`);
                    }
                    initialMonsterCount++;
                    // 使用setTimeout分批生成，避免阻塞
                    setTimeout(createInitialMonsters, 10);
                } else {
                    game.addLogEntry(`游戏初始化完成，共生成 ${game.monsters.length} 只怪物`);
                    // 分批生成初始冒险者
                    let initialAdventurerCount = 0;
                    const createInitialAdventurers = () => {
                        if (initialAdventurerCount < initialAdventurers && 
                            game.adventurers.length < Config.MAX_ADVENTURERS + (game.titleEffects.maxAdventurers || 0)) {
                            const adventurer = game.createAdventurer();
                            if (adventurer) {
                                game.addLogEntry(`初始生成冒险者: ${adventurer.name} (${adventurer.class})`);
                            }
                            initialAdventurerCount++;
                            // 使用setTimeout分批生成，避免阻塞
                            setTimeout(createInitialAdventurers, 10);
                        } else {
                            // 显示欢迎消息
                            game.showNotification('欢迎来到《冒险村放置》文字版！', 'success');
                            
                            // 强制让冒险者立即开始行动
                            game.adventurers.forEach(adventurer => {
                                adventurer.state = 'idle'; // 确保冒险者处于空闲状态，会立即寻找目标
                            });
                        }
                    };
                    createInitialAdventurers();
                }
            };
            
            // 延迟启动初始生成过程
            setTimeout(createInitialMonsters, 100);
        };
    </script>
</body>
</html>